Overkill constructor move

I have a class that contains a pointer to a large piece of allocated memory and many elements of a primitive type. I get a head from moving designers and I think this is a great opportunity to use it. Obviously the pointer should be moved, but idk if this is a good idea with primitives.

The following is a contrived class example:

class Foo { private: long m_bar = 1; /* 20+ similar members */ }; 

To make them movable, they must be dynamically distributed.

 class Foo { public: Foo(Foo && rhs) : m_bar(rhs.m_bar) { rhs.m_bar = nullptr; } ~Foo() { delete m_bar; } private: long *m_bar = new long{1}; }; 

My question is, will overhead allocations per heap cancel out the performance increase introduced by move semantics?

+4
source share
3 answers

In any case, I believe that the heap distributing each member like this will be slower. In addition to the initial heap allocation performed only by construction, holding pointers to many small non-contiguous data items on the heap do not play well with CPU caching strategies.

Some classes are very well ported because they have a large chunk of memory with a bunch of them (e.g. w990>). In your case, moving each pointer will be about as expensive as moving your smaller data types. The only way I can see that this is faster is to wrap your smaller data members in a class / structure allocated by the heap (maybe there is a unique_invest for it) and moving all of them by moving one pointer.

However, this is most likely a case of premature optimization. You might want to make the code work the way it is and determine that implementing more complex move semantics for your class can really help your code performance.

+6
source

Moving semantics only happens faster when moving an object is faster than copying. In your example, this is not true. Copying long should be the same speed as copying a pointer to a long one. Adding the semantics of movement by dynamically distributing each individual member will almost certainly slow down the work, rather than speed up the work.

Which can lead to the fact that the faster move constructor uses the PIMPL idiom. You would dynamically allocate one class that contains all the members, the main class would contain a pointer to this class. Then all you have to do is copy the pointer to the implementation class.

+2
source

If a primitive is neither large nor (in some way) more expensive to copy than a pointer, then dynamic allocation is just an additional cost.

You might want to invalidate the originals, but they do not require pointers.

+1
source

Source: https://habr.com/ru/post/1446986/


All Articles