Does shallow copy call member objects' constructors? - c++

Assuming i have this code:
class A {
public:
int x;
A(){}
A(const A& a){} //copy constructor
operator= (const A &a){...}
};
class B {
public:
A a;
B(){}
};
int main() {
B b;
B c = b; //shallow copy
B d;
d = b; //shallow assignment
}
Will the shallow copy\assignment call member A a's copy constructor\assignment operator overloading?
Or shortly does shallow copy perform member objects' user-made copy constructor & assignment operator or a shallow one as well?

The term "shallow copy" is used to describe copies where, after a "shallow copy", the two objects internally reference the same object in some way. As such, manipulating one object may conceptually manipulate a value visible through the other.
Unless the value of the int stored in A is a reference to an object somewhere, nothing in A or B references an object. Therefore, implicitly-defined copies of such objects are not "shallow" (or "deep"). That qualification simply doesn't apply to objects that aren't referencing other objects.
The implicitly defined copy constructor/assignment will perform a member-wise copy of each subobject. So long as those subobjects have copy constructors/assignment operators, they will be called by the implicitly defined versions.

Then the answer is yes, the copy constructor will be called, but the assignment operator will not.
The copy constructor will be called because the defaulted copy constructor is called, but the assignment operator is not. The defaulted assignment operator will call the defaulted copy constructor, and the defaulted copy constructor will call the copy constructor of the base class, but the defaulted assignment operator is not called.
The reason is simple: the defaulted assignment operator is not called because the defaulted assignment operator is declared "A& operator=(const A& a)".
The above is a case in which the calling convention (the "= default" is a member function calling convention) is used.

Related

Am I calling the constructor or the copy constructor? [duplicate]

I don't understand the difference between assignment constructor and copy constructor in C++. It is like this:
class A {
public:
A() {
cout << "A::A()" << endl;
}
};
// The copy constructor
A a = b;
// The assignment constructor
A c;
c = a;
// Is it right?
I want to know how to allocate memory of the assignment constructor and copy constructor?
A copy constructor is used to initialize a previously uninitialized object from some other object's data.
A(const A& rhs) : data_(rhs.data_) {}
For example:
A aa;
A a = aa; //copy constructor
An assignment operator is used to replace the data of a previously initialized object with some other object's data.
A& operator=(const A& rhs) {data_ = rhs.data_; return *this;}
For example:
A aa;
A a;
a = aa; // assignment operator
You could replace copy construction by default construction plus assignment, but that would be less efficient.
(As a side note: My implementations above are exactly the ones the compiler grants you for free, so it would not make much sense to implement them manually. If you have one of these two, it's likely that you are manually managing some resource. In that case, per The Rule of Three, you'll very likely also need the other one plus a destructor.)
The difference between the copy constructor and the assignment operator causes a lot of confusion for new programmers, but it’s really not all that difficult. Summarizing:
If a new object has to be created before the copying can occur, the copy constructor is used.
If a new object does not have to be created before the copying can occur, the assignment operator is used.
Example for assignment operator:
Base obj1(5); //calls Base class constructor
Base obj2; //calls Base class default constructor
obj2 = obj1; //calls assignment operator
Example for copy constructor:
Base obj1(5);
Base obj2 = obj1; //calls copy constructor
The first is copy initialization, the second is just assignment. There's no such thing as assignment constructor.
A aa=bb;
uses the compiler-generated copy constructor.
A cc;
cc=aa;
uses the default constructor to construct cc, and then the *assignment operator** (operator =) on an already existing object.
I want know how to allocate memory of the assignment constructor and copy constructor?
IDK what you mean by allocate memory in this case, but if you want to see what happens, you can:
class A
{
public :
A(){ cout<<"default constructor"<<endl;};
A(const A& other){ cout<<"copy constructor"<<endl;};
A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};
I also recommend you take a look at:
Why is copy constructor called instead of conversion constructor?
What is The Rule of Three?
In a simple words,
Copy constructor is called when a new object is created from an existing object, as a copy of the existing object.
And assignment operator is called when an already initialized object is assigned a new value from another existing object.
Example-
t2 = t1; // calls assignment operator, same as "t2.operator=(t1);"
Test t3 = t1; // calls copy constructor, same as "Test t3(t1);"
What #Luchian Grigore Said is implemented like this
class A
{
public :
int a;
A(){ cout<<"default constructor"<<endl;};
A(const A& other){ cout<<"copy constructor"<<endl;};
A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};
void main()
{
A sampleObj; //Calls default constructor
sampleObj.a = 10;
A copyConsObj = sampleObj; //Initializing calls copy constructor
A assignOpObj; //Calls default constrcutor
assignOpObj = sampleObj; //Object Created before so it calls assignment operator
}
OUTPUT
default constructor
copy constructor
default constructor
assignment operator
the difference between a copy constructor and an assignment constructor is:
In case of a copy constructor it creates a new object.(<classname> <o1>=<o2>)
In case of an assignment constructor it will not create any object means it apply on already created objects(<o1>=<o2>).
And the basic functionalities in both are same, they will copy the data from o2 to o1 member-by-member.
I want to add one more point on this topic.
"The operator function of assignment operator should be written only as a member function of the class." We can't make it as friend function unlike other binary or unary operator.
Something to add about copy constructor:
When passing an object by value, it will use copy constructor
When an object is returned from a function by value, it will use copy constructor
When initializing an object using the values of another object(as the example you give).

is it possible to forbid assignment if there is no explicit copy constructor? c++

Let's assume I have class with no explicit copy constructor. Is it possible to forbid operation of assigning or copying objects for this class? For example:
class A
{
// data, methods, but no copy constructor and no overloaded assignment operator
};
A object1;
A object2;
object1 = object2; // make compiler error here
A object3 = object1; // or here
You could mark the copy-constructor and copy-assignment operator as deleted:
class A
{
public:
...
A(const A&) = delete;
A& operator=(const A&) = delete;
};
If your compiler doesn't support C++11 features like this, just make the functions private.
Try this
private:
A(A const&); //Don't implement it
A& operator=(A const&);//Don't implement it
or with C++ 11
A(A const&) = delete;
A& operator=(A const&) = delete;
Let's assume I have class with no explicit copy constructor. Is it possible to forbid operation of assigning or copying objects for this class?
Derive it from boost::noncopyable, a base class that is non-copyable, or add a non-static data member that is non-copyable.
If you dont have explicit copy constructor. compiler will create a default one for you.
To forbid copying make copy constructor private.
To forbid assignment make assignment operator private
I also can declare copy constructor or assignment operator without definition. When I call either of them I get linker error.
The implicit copy constructor and assignment operator can only be called if the compiler can generate them. They (conceptually, at least) copy the base class, and then perform memberwise copy of all members. If either of those operations cannot be performed, no implicit copy constructor or assignment operator is generated.
Therefore, you can inhibit these operations by deriving from a non-copyable base class or by including a (non-static) member of a non-copyable type.
As a coding principle, I think it's clearer to explicitly declare the operations as deleted (or private, pre-C++11) members, rather than relying on the presence of a non-copyable member or base class. I'll make an exception if the member/base is named to convey that intent (e.g. boost::noncopyable).
Your question has two part:
First is Explicit constructor, the purpose of explicit constructor is to avoid the implicit construction. By implicit construction I mean
struct C {
int a;
C(int p):a(p) {}
~C(){std::cout<<"Destructor for "<<a<<'\n';}
};
int main() {
C c1 = 142; // implicit-initialization, calls C::C(42)
C c2{12}; //
return 0;
}
But if we make constructor explicit as
explicit C(int a);
Then following code will not compile.
C c1 = 142; // would not compile
This was about the explicit constructor.
Second part is avoiding copy and assignment. So, for that you have two options
As suggested by others,use boost::noncopyable
Remember "The rule of three/five/zero"
http://en.cppreference.com/w/cpp/language/rule_of_three, make your
copy ctor, move ctor & assignment operator as deleted.

What's with the copy-constructor if the class contains a user-declared destructor?

The Standard in section 12.8/7 says:
If the class definition does not explicitly declare a copy
constructor, one is declared implicitly. If the class definition
declares a move constructor or move assignment operator, the
implicitly declared copy constructor is defined as deleted; otherwise,
it is defined as defaulted (8.4). The latter case is deprecated if the
class has a user-declared copy assignment operator or a user-declared
destructor. Thus, for the class definition
struct X {
X(const X&, int);
};
a copy constructor is implicitly-declared. If the user-declared
constructor is later defined as
X::X(const X& x, int i =0) { /∗ ... ∗/ }
I can't get the point of that The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. In the example the Standard neither provides a user-declared copy assignment operator nor a destructor. What will happen if we declare a destructor or a copy assignment operator? I've tried to do that as follows:
struct A
{
~A(){ };
};
A::A(const A&){ }; //error
int main(){ }
DEMO
but in the example we still have the implicitly-declared copy constructor. What does that rule actual mean?
I thought that if we write the following:
struct A
{
A(){ };
A(const A&&){ };
~A(){ };
};
A a;
A t = a; //error: call to implicitly-deleted copy constructor of 'A'
int main()
{
}
DEMO
the copy-constructor won't explicitly deleted. But thats's not the case.
This deprecation basically incorporates the Rule of Three (Five). If a user-declared copy assignment operator or destructor is provided, the fact that the copy constructor is defined as defaulted (and not as deleted) is deprecated. That should prevent you from depending upon such an implicitly declared copy constructor in future.
In the example the Standard provides neither copy assignment nor
destructor are user-decalred.
The example has nothing to do with the deprecation.
I've tryied to do that as follows: […] but in the example we still have the impliclty-declared copy
constructor.
You cannot define an implicitly declared copy constructor - because it's already defined, by = default (no pun intended). You would have to declare it yourself first.
I thought that If we wirte the following: […] the copy-constructor won't explicitly deleted. But it's not true.
You quoted the rule that explicitly specifies that the copy constructor will be implicitly defined as deleted if a move constructor is declared:
If the class definition declares a move constructor or move
assignment operator, the implicitly declared copy constructor is
defined as deleted;
Clearly,
A(const A&&){ }
Is a move constructor according to [class.copy]/3. If you removed this move constructor then your example compiles, although it uses said deprecated feature.
Deprecated normally means that something will work, but that it is frowned upon and may not work in the future. I think the standard is saying that if you create a user-declared copy assignment operator or a user-declared destructor it will still create a default copy constructor (if you haven't) - but it may not in the future. So they want you to create your own copy constructor now, if you have one of the other two, and in the future they may force you to.

Conditions under which compiler will not define implicits (constructor, destructor, copy constructor, copy assignment) [duplicate]

This question already has answers here:
Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?
(3 answers)
Closed 9 years ago.
This is supposed to be a trivial question but I could not find it explicitly on stackoverflow.
The following will be defined implicitly if not provided by the user.
default (parameterless) constructor
copy constructor
copy assignment operator
destructor
But I have read somewhere (which I cant seem to find now), that there are some conditions where the compiler will not implicitly implement them.
What are these conditions?
The Default Constuctor (e.g., X()) will not be implicitly generated if:
you have explicitly declared any constructor at all
there is a data member that is not default-constructible (such as a reference, a const object, or a class with no or inaccessible default constructor)
(C++11) you have explicitly told the compiler to not generate one using X() = delete;
The Copy Constructor (e.g., X(const X&)) will not be implicitly generated if:
you have explicitly declared a copy constructor (for class X a constructor taking X, X& or const X&)
there is a data member that is not copy-constructible (such as a class with no or inaccessible copy constructor)
the base class is not copy-constructible
(C++11) you have declared a move constructor or move assignment operator
(C++11) you have explicitly told the compiler to not generate one using X(const X&) = delete;
The Copy Assignment Operator (e.g., X& operator=(const X&)) will not be implicitly generated if:
you have explicitly declared a copy assignment operator (for class X an operator= taking X, X& or const X&)
there is a data member in your class that is not copy-assignable (such as a reference, a const object, or a class with no or inaccessible assignment operator)
the base class is not copy-assignable
(C++11) you have declared a move constructor or move assignment operator
(C++11) you have explicitly told the compiler to not generate one using X& operator=(const X&) = delete;
The Destructor (e.g., ~X()) will not be implicitly generated if:
you have explicitly declared a destructor
(C++11) you have explicitly told the compiler to not generate one using ~X() = delete;
The Move Constructor (C++11) (e.g., X(X&&)) will not be implicitly generated if:
you have explicitly declared a move constructor (for class X, a constructor taking X&&)
you have declared a copy assignment operator, copy constructor, destructor, or move assignment operator
there is a data member in your class that cannot be move-constructed (is const, is a reference, or has a deleted, inaccessible, or ambiguous move constructor)
the base class cannot be move-constructed
you have explicitly told the compiler to not generate one using X(X&&) = delete;
The Move Assignment Operator (C++11) (e.g., X& operator=(X&&)) will not be implicitly generated if:
you have explicitly declared a move assignment operator (for class X, an operator= taking X&&)
you have declared a copy assignment operator, copy constructor, destructor, or move constructor
there is a data member in your class that cannot be move-assigned (is const, is a reference, or has a deleted, inaccessible, or ambiguous move assignment operator)
the base class cannot be move-assigned
you have explicitly told the compiler to not generate one using X& operator=(X&&) = delete;

C++: autogenerated(default) copy costructor

If I declare a class like, (no dynamic memory allocation, no pointer):
class A{
int a,b;
public:
A();
A(int,int);
A& operator=(const A);
};
Is it safe not to declare a copy constructor? How does the default copy constructor looks like?
A& A::operator=(const A other)
{
a=other.a;
b=other.b;
return *this;
}
Even If I do not declare a copy constructor, the default one will be called when I call operator=()
EDIT:
the default destructor is:
A::~A(){}
so it's not needed here
The rule is that if you need to provide either:
copy constructor or
destructor or
copy assignment operator
then you probably need to provide all three of them. This rule is known as Rule of Three.
Is it safe not to declare a copy constructor?
It is safe.
Do you have to for your example case?
Not really. To be specific the rule of three governs that. Check the linked question for more details on that.
How does the default copy constructor looks like?
I gather this is asking, What does the default copy constructor do.
This is answered in:
C++03 Standard 12.8 Copying class objects:
Para 8:
The implicitly-defined copy constructor for class X performs a memberwise copy of its subobjects. The order of copying is the same as the order of initialization of bases and members in a user-defined constructor (see 12.6.2). Each subobject is copied in the manner appropriate to its type:
— if the subobject is of class type, the copy constructor for the class is used;
— if the subobject is an array, each element is copied, in the manner appropriate to the element type;
— if the subobject is of scalar type, the built-in assignment operator is used.
Virtual base class subobjects shall be copied only once by the implicitly-defined copy constructor (see 12.6.2).
Even If I not declare a copy constructor, the default one will be called when I call operator=()
A copy constructor is invoked only when a copy of the class object needs to be created. This involves copies of objects created while passing to or returning from functions.
Your copy assignment operator passes the object A by value, this pass by value is achieved by passing a copy of the object through copy constructor and hence the call to copy constructor.
To avoid the copy you need to pass by reference:
A& A::operator=(const A& other)
Good Read:
What's the difference between passing by reference vs. passing by value?
You seem to be confusing copy-constructors with copy-assignment operators. The implicitly generated copy-constructor will copy-construct each of the members:
A::A( A const& source )
: a( source.a )
, b( source.b )
{}
The implicitly generated copy-assignment operator will copy-assign each of the members:
A& A::operator =( A const& source )
{
a = source.a;
b = source.b;
return *this;
}
The copy-assignment operator as you defined it in your question takes an A by copy, so the copy-constructor will be called to create the argument passed to operator=. Note that the copy may be elided under certain circumstances.
Your class provides operator=. Per the rule of three (as #AlokSave says), you should then provide the copy constructor and destructor as well.
The question is, if you're happy with the default-supplied copy constructor, why aren't you happy with the default-supplied copy assignment operator? And if you are, just don't declare operator= and let the compiler generate the entire "rule of three" for you.
A::A(const A& other) != A& A::operator=(const A other)