As I know that C++ compiler creates a copy constructor for each class. In which cases we have to write user defined copy constructors? Can you give some examples?
The copy constructor generated by the compiler does member-wise copying. Sometimes that is not sufficient. For example:
class Class {
public:
Class( const char* str );
~Class();
private:
char* stored;
};
Class::Class( const char* str )
{
stored = new char[srtlen( str ) + 1 ];
strcpy( stored, str );
}
Class::~Class()
{
delete[] stored;
}
in this case member-wise copying of stored
member will not duplicate the buffer (only the pointer will be copied), so the first to be destroyed copy sharing the buffer will call delete[]
successfully and the second will run into undefined behavior. You need deep copying copy constructor (and assignment operator as well).
Class::Class( const Class& another )
{
stored = new char[strlen(another.stored) + 1];
strcpy( stored, another.stored );
}
void Class::operator = ( const Class& another )
{
char* temp = new char[strlen(another.stored) + 1];
strcpy( temp, another.stored);
delete[] stored;
stored = temp;
}
If you have a class that has dynamically allocated content. For example you store the title of a book as a char * and set the title with new, copy will not work.
You would have to write a copy constructor that does title = new char[length+1]
and then strcpy(title, titleIn)
. The copy constructor would just do a "shallow" copy.
Copy Constructor is called when an object is either passed by value, returned by value, or explicitly copied. If there is no copy constructor, c++ creates a default copy constructor which makes a shallow copy. If the object has no pointers to dynamically allocated memory then shallow copy will do.
I am a bit peeved that the rule of the Big Three
wasn't cited.
This rule is very simple:
The Big Three:
Whenever you are writing either one of Destructor, Copy Constructor or Copy Assignment Operator, you probably need to write the other two.
But there is a more general guideline that you should follow, which derives from the need to write exception-safe code:
Each resource should be managed by a dedicated object
Here sharptooth
's code is still (mostly) fine, however if he were to add a second attribute to his class it would not be. Consider the following class:
class Erroneous
{
public:
Erroneous();
// ... others
private:
Foo* mFoo;
Bar* mBar;
};
Erroneous::Erroneous(): mFoo(new Foo()), mBar(new Bar()) {}
What happens if new Bar
throws ? How do you delete the object pointed to by mFoo
? There are solutions (function level try/catch ...), they just don't scale.
The proper way to deal with the situation is to use proper classes instead of raw pointers.
class Righteous
{
public:
private:
std::unique_ptr<Foo> mFoo;
std::unique_ptr<Bar> mBar;
};
With the same constructor implementation (yes, the same), I now have exception safety for free!!! Isn't it exciting ? And best of all, I no longer need to worry about a proper destructor! I do need to write my own Copy Constructor
and Assignment Operator
though, because unique_ptr
does not define these operations... but it doesn't matter here ;)
And therefore, sharptooth
's class revisited:
class Class
{
public:
Class(char const* str): mData(str) {}
private:
std::string mData;
};
I don't know about you, but I find mine easier ;)
It's often a good idea to disable copy ctor, and operator= unless the class specifically needs it. This may prevent inefficiencies such as passing an arg by value when reference is intended. Also the compiler generated methods may be invalid.