class WithCC {
public:
WithCC() {}
WithCC(const WithCC&) {
cout << "in WithCC's copy constructor" << endl;
}
};
class Composite {
WithCC withcc; // Embedded objects
public:
Composite() {}
};
int main() {
Composite c;
Composite c2 = c;
}
With the code above, withcc's copy constructor gets called and I get the output:
in WithCC's copy constructor
But if I add a copy constructor to Composite like this...
class Composite {
WithCC withcc; // Embedded objects
public:
Composite() {}
Composite(const Composite&) {
cout << "in composite's copy constructor" << endl;
}
};
withcc's copy constructor doesn't seem to get called because the output is:
in composite's copy constructor
Why isn't withcc's copy constructor called here?
In the first sample you omitted a copy constructor for Composite and hence C++ generated a default one for you. This default one essentially runs a field by field copy and hence was running the copy constructor of WithCC.
When you explicitly defined a copy constructor C++ does no magic. It is up to you to copy the fields as necessary. For example
Composite(const Composite& other) : withcc(other.withcc) {
cout << "in composite's copy constructor" << endl;
}
The copy constructor implicitly defined by the compiler performs a memberwise copy/move of its bases and members.
A user-defined copy-constructor defaault initializes subobjects of the derived class if their constructors were not called explicitly in the ctor-list.
So in your last code snippet you defined explicitly the copy constructor
Composite(const Composite&) {
cout << "in composite's copy constructor" << endl;
}
but its ctor list is empty. So data member withcc will be default initialized.
I described this more detailed in my article
Implicitly defined copy constructor and explicitly defined copy constructor: what is the difference?
Though it is written in Russian but you will be able to read it using for example google service translare.
Related
As the subject,the related code is:
#include <iostream>
class ABC
{ public:
ABC()
{
std::cout<< "default construction" << std::endl;
}
ABC(const ABC& a)
{
std::cout << "copy construction" << std::endl;
}
ABC(const ABC&& a)
{
std::cout << "move construction" << std::endl;
}
};
int main()
{
ABC c1 = ABC();
return 0;
}
Output with -fno-elide-constructors -std=c++11
default construction
move construction
If i remove the move constructor above, then the output is:
default construction
copy construction
why copy construction could be used while move constructor has been removed?You see, if there is a user defined move constructor, the compiler prefer to use move constructor.
As per some documentation,compiler provides a default move constructor.**So why don't the compiler use the default move constructor?
I am a novice in C++.I would be grateful to have some help with this question.
As per some documentation,compiler provides a default move constructor.
Let's take a look at some documentation. The following is from cppreference.com.
If [conditions] then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).
You're right. The compiler does provide a defualt move constructor under the right conditions. However, those conditions are important. The first condition you seem to be aware of: there cannot be a user-defined move constructor. So that just leaves this list of conditions:
there are no user-declared copy constructors;
there are no user-declared copy assignment operators;
there are no user-declared move assignment operators;
there is no user-declared destructor;
And there you go. Your user-defined copy constructor is preventing the compiler from providing a default move constructor. Hence there is no move constructor to use.
When I read about copy constructor and copy assignment constructor, what I understood is that both gives away their properties one to another, and that both of them are declared implicitly by compiler (if not defined). So both must be exist whether doing something useful or not.
Then I tested this code:
#include <iostream>
using namespace std;
class Test {
public:
Test () {
cout << "Default constructor" << endl;
}
Test (const Test& empty) {
cout << "Copy constructor" << endl;
}
Test& operator=(const Test& empty) {
cout << "Copy assignment operator" << endl;
}
private:
};
int main () {
Test a; // Test default constructor
Test b (a); // Test copy constructor
Test c = b; // Test copy assignment constructor
system ("pause");
return 0;
}
But it seems the copy assignment operator is not called at all. I tried with three conditions:
Everything included. It prints out:
// Default constructor
// Copy constructor
// Copy constructor # Why not prints out "Copy assignment operator"?
Whitout copy assignment operator just copy constructor. It prints out:
// Default constructor
// Copy constructor
// Copy constructor # Why it's printed out even though I didn't define it?
Whitout copy constructor just copy assignment operator. It prints out:
// Default constructor # Why "Copy assignment operator" is not printed out?
Only constructor. It prints out:
// Default constructor # Understandable
So, it's like the compiler doesn't even care if I define the copy assignment operator or not. None of the four examples above prints out "Copy assignment operator". So when did it get called, if it is really exists and has a meaning?
Test c = b is an initialization, not an assignment.
If you had done this:
Test c;
c = b;
Then it would have called the copy assignment operator.
here is a class definition with 3 different constructors, one default, one integer parametrized and a copy constructor. R-value objects are created and operated on just after creation. The first two cases work as expected but in the final case two constructor invocation is expected but only the first one takes place. Why so? Following is the code.
#include <iostream>
using namespace std;
class A
{
int i;
public:
A() {cout << "In default ctor\n";};
A(int v) {cout << "Setting i in par-ctor to " << v << "\n"; i=v;}
A(const A& o) {cout << "In copy ctor, changing i to " << o.i << "\n"; i=o.i;}
void print() {cout << "i = " << i << endl;}
};
int main()
{
A o(10);
A(o).print(); // invokes copy constructor A(const A&) as expected
A(20).print(); // invokes int parametrized constructor A(int)
A(A(30)).print(); // invokes only int constructor A(int) and not copy constructor, why so?
return(0);
}
The output is:
Setting i in par-ctor to 10
In copy ctor, changing i to 10
i = 10
Setting i in par-ctor to 20
i = 20
Setting i in par-ctor to 30
i = 30
The C++ standard explicitly allows compilers to omit copies in certain situations. This is known as copy elision. One such situation is as you've shown:
when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
Note that copy elision is optional. Your compiler happens to be treating that line like A(30).print();, but it doesn't have to.
I Have just created a class with an integer variable and a pointer variable. After creating its object , I passed it to a function. Even after returning the function the program is not throwing the exception
#include"iostream"
using namespace std;
class A
{
public :
int i;
char *c;
void show();
};
void func(A obj);
int main()
{
A a;
a.i = 10;
a.c = "string";
cout << " Before Fun " << endl;
a.show();
cout << " Going To Call func " << endl;
func(a);
cout << " After func " << endl;
a.show();
return 0;
}
void A::show()
{
cout << " The valuses in Object are " << i << '\t' << c << endl;
}
void func(A aa)
{
cout << " The valuses in Object are " << aa.i << '\t' << aa.c << endl;
}
In The Func I am passing the object a (from main) and it would get copied in aa (stack of func). so after returning from the func if i call show ( the pointer c would be null of a), It would give me exception
But it is not happening . please help me to prove the requirement of copy constructor
Hide the copy constructor. That will cause a compilation error everywhere it is called implicitly.
class A
{
public :
int i;
char *c;
private:
A(const A& _other);
};
If no copy constructor is declared for an object, one is implicitly defined. This copy constructor copies each element of the object.
In your example, the call to func(a) will call this copy constructor, and so aa will be a copy of a (aa.i will be 10 and aa.c will point to the first element of "string").
If you are using C++11 you can do the following to remove the copy constructor
class A
{
public :
int i;
char *c;
void operator=(const A& _other) = delete;
A(const A& _other) = delete;
};
or even better:
class A : public NonCopyable // perhaps std:: or if you prefer boost, boost::
{
public :
int i;
char *c;
};
http://en.wikipedia.org/wiki/C++11#Explicitly_defaulted_and_deleted_special_member_functions
When you make a class, a null constructor and copy constructor exist implicitly.
So that is why it does not throw an exception.
However, if you define ANY constructor, you will then need to define others otherwise the rest of the constructors will be overwritten.
For example, you define a null constructor only. Then it will throw an exception. Because the implicitly defined copy constructor will be overridden.
This is one way of proving the need of a copy constructor.
An implicit copy constructor does exist if you do not define one explicitly. It is called in your func() function. A object is copied and assigned a value for its member i.
Result will be: that you do get with show() the value for i that you had before when calling func. This is with no surprise because you are not doing any assignment to members of A inside A.
Implicit copy constructor by the compiler provide member-wise copy. This is what you may need in most cases.
When is default constructor not sufficient ? you have pointer like members, and need a deep-copy of it. You don't want to copy the pointer (what copy constructor would do), but rather to have the object pointed to copied. But why do you need deep copy ? You don't want to copy the pointer (which is owned by any instance of the class), and end up calling twice destructor on the same pointer. From the second call to delete on this pointer, heap corruption ensues. You may also need copy constructor made explicit for shared_pointers.
Note that, for performance reasons, it is best pass object by const reference than by value.
In your case the copy constructor provided by compiler is present.
Modify your code and write a copy constructor as:
//Default and copy constructor
A()
{
i = 0;
c = NULL;
}
A(const A& _other)
{
cout<<"In copy cons"<<endl;
}
When you will modify the code as per above when func gets called then your own copy constructor gets called in this case you will get the junk values(can not predict)
And if you modify your copy constructor code as
A(const A& _other)
{
cout<<"In copy cons"<<endl;
i = _other.i;
c = new char [(strlen(_other.c) +1)];
strcpy(c,_other.c);
}
Now you can see the differnce in both outputs and the use of Copy constructor how and where it's used.
Consider the sample code below:
#include <iostream>
using namespace std;
class core
{
public:
core(const core& obj)
{
cout << "core copy ctor called\n";
}
core()
{
cout << "core default ctor called\n";
}
};
class sample : public core
{
public:
sample()
{
cout << "sample default ctor called\n";
}
#if 0
sample(const sample& obj)
{
cout << "sample copy ctor called\n";
}
#endif
};
int main()
{
sample s1;
sample s2 = s1; //Line1
return 0;
}
Type1: Copy constructor not declared explicitly for class sample
(Type1 is shown in the code above. Then the copy constructor of class sample is implicitly generated by the compiler).
When the statement, Line1 is executed, first the copy constructor of class core is invoked, and then the copy constructor of class sample is invoked.
Type2: Copy constructor defined explicitly for class sample
When the statement, Line1 is executed, first the default constructor of class core is invoked, and then the copy constructor of class sample is invoked.
Question:
Why is this difference in behavior for copy constructor as mentioned in Type1 and Type2 ?
Because the copy constructor you explicitly define for sample doesn't ask for core's copy constructor to be invoked. You'd have to write : core(obj) if you wanted to make that happen.
Put another way, when you write an explicit copy constructor, you are taking charge of the copy construction of sample, including its core sub-object. By writing it the way you have done, you have chosen not to initialise the core sub-object using obj. Since you haven't said how you do want it initialised, the compiler just uses core's default constructor instead, hence the behaviour in the second case you outline.
By contrast, in the first case, the compiler-generated default copy constructor for sample does ask for the core sub-object to be initialised using core's copy constructor, hence the observed behaviour.