I know that the compiler sometimes provides a default copy constructor if you don't implement yourself. I am confused about what exactly this constructor does. If I have a class that contains other objects, none of which have a declared copy constructor, what will the behavior be? For example, a class like this:
class Foo { Bar bar; }; class Bar { int i; Baz baz; }; class Baz { int j; };
Now if I do this:
Foo f1; Foo f2(f1);
What will the default copy constructor do? Will the compiler-generated copy constructor in Foo
call the compiler-generated constructor in Bar
to copy over bar
, which will then call the compiler-generated copy constructor in Baz
?
An implicitly defined copy constructor will copy the bases and members of an object in the same order that a constructor would initialize the bases and members of the object.
Can copy constructor be used to initialize one class object with another class object? Explanation: The restriction for copy constructor is that it must be used with the object of same class. Even if the classes are exactly same the constructor won't be able to access all the members of another class.
Because, now we have explicitly provided a matching 'copy' constructor. So, saying 'Inheriting copy constructors are now allowed' is invalid.
A copy constructor has one parameter that is a reference to the type that is copied. It can have additional parameters, if these have default values.
Foo f1; Foo f2(f1);
Yes this will do what you expect it to:
The f2 copy constructor Foo::Foo(Foo const&) is called.
This copy constructs its base class and then each member (recursively)
If you define a class like this:
class X: public Y { private: int m_a; char* m_b; Z m_c; };
The following methods will be defined by your compiler.
There are actually two default constructors.
One is used for zero-initialization
while the other is used for value-initialization
. The used depends on whether you use ()
during initialization or not.
// Zero-Initialization compiler generated constructor X::X() :Y() // Calls the base constructor // If this is compiler generated use // the `Zero-Initialization version' ,m_a(0) // Default construction of basic PODS zeros them ,m_b(0) // m_c() // Calls the default constructor of Z // If this is compiler generated use // the `Zero-Initialization version' { } // Value-Initialization compiler generated constructor X::X() :Y() // Calls the base constructor // If this is compiler generated use // the `Value-Initialization version' //,m_a() // Default construction of basic PODS does nothing //,m_b() // The values are un-initialized. m_c() // Calls the default constructor of Z // If this is compiler generated use // the `Value-Initialization version' { }
Notes: If the base class or any members do not have a valid visible default constructor then the default constructor can not be generated. This is not an error unless your code tries to use the default constructor (then only a compile time error).
X::X(X const& copy) :Y(copy) // Calls the base copy constructor ,m_a(copy.m_a) // Calls each members copy constructor ,m_b(copy.m_b) ,m_c(copy.m_c) {}
Notes: If the base class or any members do not have a valid visible copy constructor then the copy constructor can not be generated. This is not an error unless your code tries to use the copy constructor (then only a compile time error).
X& operator=(X const& copy) { Y::operator=(copy); // Calls the base assignment operator m_a = copy.m_a; // Calls each members assignment operator m_b = copy.m_b; m_c = copy.m_c; return *this; }
Notes: If the base class or any members do not have a valid viable assignment operator then the assignment operator can not be generated. This is not an error unless your code tries to use the assignment operator (then only a compile time error).
X::~X() { // First runs the destructor code } // This is psudo code. // But the equiv of this code happens in every destructor m_c.~Z(); // Calls the destructor for each member // m_b // PODs and pointers destructors do nothing // m_a ~Y(); // Call the base class destructor
Looking at your code the following copy constructors are generated:
Foo::Foo(Foo const& copy) :bar(copy.bar) {} Bar::Bar(Bar const& copy) :i(copy.i) ,baz(copy.baz) {} Baz::Baz(Baz const& copy) :j(copy.j) {}
The compiler provides a copy constructor unless you declare (note: not define) one yourself. The compiler-generated copy constructor simply calls the copy constructor of each member of the class (and of each base class).
The very same is true for the assignment operator and the destructor, BTW. It is different for the default constructor, though: That is provided by the compiler only if you do not declare any other constructor yourself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With