3

Do we only need to write a copy constructor and assignment operator when we have pointer data members (because otherwise two pointers could point to the same object when the compiler-generated copy ctor does a shallow copy)?

If all our data members are allocated on the stack we can just rely on compiler-defined copy constructor and assignment operator?

user997112
  • 29,025
  • 43
  • 182
  • 361
  • 1
    Please refer to the *Rule of Three*. It is helpful to know that if you acquire any kind of resource and you need to dispose or clean up, you probably need to define the three operations (four in C++11 to deal with move semantics): http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three – Escualo Oct 26 '13 at 17:46

4 Answers4

4

Pointers are undoubtedly the most obvious case, but not really the only one.

Another example would be a class that opens a database connection in the ctor and closes it in the dtor. A copy ctor would need to do something to duplicate the database connection, so the copy's connection to the database is closed separately from the original's connection.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

Use the compiler defined copy constructor if it works. The shallow copy is typically faster, and even though they may cope the pointer address instead of the pointed data that can be what you want in some cases. For example you might want a pointer to the texture that you share with other parts of the code.

Only if you need a copy of the data you should fix the copy constructor.

A warning would be member variables that are classes with their own copy constructors, can't give you any promises on what happens then.

Bozemoto
  • 226
  • 2
  • 6
0

If a base class or an object contained by the class has no copy constructor (ie. a stream) then if you wish your class to be copy constructable then you must implement a copy constructor.

For the stream case, this copy constructor may have to

a) duplicate the file,

b) create a new empty file that can be written to,

c) or save the address of the stream so that both objects can write to it.

The last option is the most complicated and would probably require use of a shared_ptr.

0

Generally, I like to put all my resources into classes maintaining these resources and these tesource maintainer need a copy construct, copy assignment, and a destructor. Depending on the resource, the copy constructor and copy assignment may be deleted.

What is not as obvious is that some classes not maintaining resources directly may need a copy assignment: if you want your copy assignment to be strongly exception safe, you often need to implement the copy assignment. For example, assume your class stores two vectors. The generated copy assgnment does a memberwise assignment. Normally, memberwise assignment is fine. However, if the assgnment to the second vector throws an exception, it is impossible to restore the original state! A better copy assgnment would look like that:

T& T::operator= (T other) {
    other. swap(*this);
    return *this;
}

Since swap() can be implemented without throwing, This imolementation is strongly exception-safe.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380