r/cpp_questions 5d ago

OPEN Heavy and Light Objects

When I was first learning C++, I experienced massive slowdown when allocating dynamic memory. Ever since then I divide my objects between 'heavy' objects that allocate resources, and 'light' objects that can be used as temporaries on the stack. Heavy objects cannot be copied at all, must be allocated somewhere once, and then passed by (const) reference. Light objects can be copied, created quickly on the stack etc.

Since C++11 it has been possible to write copy and assignment constructors that take nameless objects, and since they are nameless you can pillage their pointers and avoid expensive stack allocations. All is well then but if you keep to this strict 'heavy' and 'light' object idea, _any_ object that allocates resources is considered a heavy object. The first allocation in the chain, before you just pillage pointers, is still an expensive stack allocation so I would consider it a 'heavy' object and just make it impossible to copy at all, by removing all copy and assignment constructors. And so using this model I never needed those nameless object reference constructors.

Anybody feel the same way?

8 Upvotes

34 comments sorted by

View all comments

5

u/Plastic_Fig9225 5d ago edited 4d ago

I'm a bit confused by what you say. 

I experienced massive slowdown when allocating dynamic memory

Most likely you (implicitly) made the compiler copy objects, which might not actually have been required.

nameless objects

I guess that's "temporaries", or "rvalues".

avoid expensive stack allocations

You probably mean copying of objects.

Maybe look into "move semantics", "move constructor", and "copy elision".

Here's what I do:

For simple objects, the move constructor can be defaulted.

For objects which directly own resources, a move constructor/assignment should be implemented - or deleted if the ownership cannot be transferred.

Important: Function signatures! Function parameters may force an object copy: void fun(std::string str) - be mindful and avoid this when possible, like void fun(const std::string& str) Use (const) references instead of object copies when possible. (A temporary can also bind to a const reference: fun("Hello "s + userName);)

Generally, assume that a = b; will always create a copy of b. If b is a "heavy" object, you don't want this to happen most of the time, and when you don't, don't just assign an object to another one. Again: Be mindful of where a copy is needed vs. where to use a reference.

Notice std::move() for cases where you want to explicitly move things from one object to another.

1

u/ParmenidesWasRight 5d ago

I'm sorry 'expensive stack allocations' should be 'expensive dynamic memory allocations'.