Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

move constructor overkill

I have a class that holds a pointer to a large chunk of allocated memory and lots of primitive type members. I'm getting my head around move constructors and think this is a perfect opportunity to use one. Obviously the pointer should be moved over but idk if it's a good idea with the primitives.

Below is a contrived example of the class:

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

To make them movable, they would have to be dynamically allocated.

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 the overhead of allocating on the heap nullify the performance increase introduced by the move semantics?

like image 431
Ilia Choly Avatar asked Jan 14 '23 23:01

Ilia Choly


2 Answers

If anything, I believe heap allocating each member like this will end up being slower. On top of the initial heap allocation, performed only on construction, holding pointers to many small, non-contiguous data members on the heap does not play nicely with CPU caching strategies.

Some classes move very well because they have a large heap-allocated bit of memory (std::string for example). In your case, moving each pointer is going to be just about as expensive as moving your smaller data types. The only way I can see this being faster is if you wrap your smaller data members in a class/struct that is heap allocated (perhaps holding a unique_pointer to it.) and moving all of them via the single pointer's move.

That said, this is very likely a case of premature optimization. You may may want to get the code working how it is and determine that implementing more complicated move semantics for your class really could really help your code's performance.

like image 121
Sean Cline Avatar answered Jan 25 '23 04:01

Sean Cline


Move semantics is only faster when moving the object is faster that copying it. In your example, that isn't true. Copying a long should be the same speed copying a pointer to a long. Adding move semantics by dynamically allocating each individual member will almost certainly slow things down, rather than speed things up.

What might result in a faster move constructor is using the PIMPL idiom. You would dynamically allocate one class that contains all of the members, the main class would only contain a pointer to that class. Then, all your move constructor would have to do is copy the pointer to the implementation class.

like image 24
Dirk Holsopple Avatar answered Jan 25 '23 05:01

Dirk Holsopple