9

I'm reading C++ Primer, 3rd Ed (Lippman and Lajoie) and it's saying that when a vector needs to be reallocated in order to make space for more elements added with push_back(), the elements are copy-constructed in the new space and then the destructor is called on the old elements. I'm confused about why this is necessary - why can't the data just be copied bit-for-bit? I assume that the answer has to do with dynamic memory allocation, but my current line of reasoning is that even if the vector elements handle dynamic memory, the data actually stored in the elements will be pointers, meaning bitwise copying will preserve the location they point to and won't present any problems. I can see how re-locating the dynamically-allocated memory that the elements point to would be a problem, since it would invalidate the pointers, but as far as I can tell the vector re-location would have no reason to do that.

Can someone give me a simple example of a class which shouldn't be moved bit-by-bit?

user1476176
  • 1,045
  • 1
  • 7
  • 15
  • 2
    The scenario where the constructor/destructor register/unregister the address of the class with a parent object comes to mind. – ta.speot.is Jun 23 '12 at 01:03
  • 2
    The scenario where the type is not _trivially copyable_ comes to mind. – K-ballo Jun 23 '12 at 01:04
  • 2
    ta.spot.is has a solid example, though I wouldn't call every object registry a "parent". Separately, some classes may keep pointers to their own data members - for example, to model some modal state, saying some future operations should now be affecting that specific member, or having an iterator into an internal vector. – Tony Delroy Jun 23 '12 at 01:25
  • Note that you can write your class using the pointer-to-implementation idiom to basically reduce the copy constructor to a bit-by-bit situation, or just store smart pointers, if you run into a real life situation where this comes up. – djechlin Jun 23 '12 at 04:56
  • Of course, chances are your smart pointers aren't going to be happy being bit copied... – Managu Jun 23 '12 at 05:38
  • They have finally fixed this by introducing move semantics in the latest revisions of the language. But I'm interested too in convincing example of why all that value copying was necesary in the first place. – Oleg Kolosov Jun 23 '12 at 10:03

2 Answers2

8

Here's probably the simplest (but rather contrived) example:

class foo
{
  int i;
  int* pi; // always points to i
};

Here, the copy constructor would maintain the invariant that pi points to i. The compiler itself wouldn't be able to figure out this relationship on its own, hence the need to call the copy constructor.

jjlin
  • 4,462
  • 1
  • 30
  • 23
4

Can someone give me a simple example of a class which shouldn't be moved bit-by-bit?

By the standard, doing a memcpy on any class that isn't a POD in C++03 (or trivially copyable in C++11) would qualify. memcpying non-PODs (or non-trivially copyable) invokes undefined behavior; therefore an actual copy (or in C++11, move) constructor must be used.

So std::vector itself applies, since it is not a POD type (and in C++11, it's not trivially copyable).

Community
  • 1
  • 1
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982