I have declared a Point class like this :
class Point{
private :
int a,b;
public :
Point(Point const &p) {
a = p.a + 1;
b = 0;
}
Point(){a=2; b=3;}
int getX(){return a;}
int getY(){return b;}
};
int main(){
Point p1,p2;
p2=p1;
cout << p2.getX(); // 2
cout << p2.getY(); // 3
}
Why the copy constructor is not called ? as it's called here :
int main(){
Point p1;
Point p2=p1;
cout << p2.getX(); // 3
cout << p2.getY(); // 0
}
This is copy construction
Point p2=p1; // p2 is constructed here.
// This is shorthand for Point p2(p1);
This is assignment
p2=p1; // p2 already exists (it was created on the previous line).
The assignment operator is defined with:
// If you don't define this the compiler will generate one for you.
Point& operator=(Point const& rhs)
{
// Copy for rhs into this.
return *this;
}
// The compiler generated one looks like this:
Point& operator=(Point const& rhs)
{
a = rhs.a;
b = rhs.b;
return *this;
}
In the first program
int main(){
Point p1,p2;
p2=p1;
^^^^^
there is called the copy assignment operator created by the compiler implicitly.
In this program object p2 was already created using the default constructor
Point p1,p2;
In tfhe second program
int main(){
Point p1;
Point p2=p1;
^^^^^^^^^^^
there is indeed called the copy constructor.
Point p1,p2;
p2=p1;
p2 is already constructed so the second statement invokes the assignment operator
Point p1;
Point p2=p1;
Here p2 is copy-constructed since it had not been constructed before.
Consider this code:
#include <iostream>
class A {
public:
A() { std::cout << "Ctor called\n"; }
A(const A&) { std::cout << "Copy Ctor called\n"; }
A& operator=(const A&) { std::cout << "Assignment operator called\n"; return *this;}
};
int main() {
A a,b;
b = a;
A c;
A d = c;
}
the output of which is enlightening:
Argento:Desktop marinos$ clang++ test.cpp -o test
Argento:Desktop marinos$ ./test
Ctor called
Ctor called
Assignment operator called
Ctor called
Copy Ctor called
Related
The following code:
#include <iostream>
#include <string>
using namespace std;
void print(string a) { cout << a << endl; }
void print(string a, string b) { cout << a << b << endl; }
class A {
public:
string p;
A() { print("default constructor"); }
A(string a){ p = a; print("string constructor ", p); }
A(const A& o) { print("copy constructor"); }
A (A&& o) { print("move constructor"); }
A& operator=(const A& o) { print("copy assignment"); return *this; }
A& operator=(const A&& o) { cout << "move assignment to:" << p << " from:" << o.p << endl; return *this; }
~A() { print("destructor ", p); }
};
A operator+(const A& a, const A& b) {
cout << "add" <<endl;
A c("f");
return c;
}
A f(A& a, A& b, A& c) {
A d("e");
d = a+b+c;
print("after add");
return d;
}
int main() {
A a("a"); A b("b"); A c("c");
A whereDidThisGo {f(a,b,c)};
print("end");
}
has the following output:
string constructor a
string constructor b
string constructor c
string constructor e
add
string constructor f
add
string constructor f
move assignment to:e from:f
destructor f
destructor f
after add
end
destructor e
destructor c
destructor b
destructor a
Process exited after 0.06744 seconds with return value 0
Press any key to continue . . .
Where is the construction/destruction of the whereDidThisGo variable defined in main?
Where is the construction/destruction of the whereDidThisGo variable defined in main?
You do not see the ouptut for this due to named return value optimization(aka NRVO).
it's not a good optimization for people like me who are trying to learn constructors
You can disable this NRVO by providing the -fno-elide-constructors flag to the compiler. Demo.
Also, note that in your example the A::operator=(const A&&) should instead be:
//-----------vv------->no need for const here
A::operator=(A&&)
TIL about NRVO, it's not a good optimization for people like me who are trying to learn constructors haha.
Thank you for the answers, yes the move assignment should be a non-const pointer, I simply overlooked it.
I have question on the below code. In the main function what will happen when the line: obj = 20; is executed. I am not able to understand why it calls the constructor? Could anyone of you please explain?
#include <iostream>
#include <string>
using namespace std;
class Int {
int x;
public:
Int(int x_in = 0)
: x{ x_in }
{
cout << "Conversion Ctor called" << endl;
}
operator string()
{
cout << "Conversion Operator" << endl;
return to_string(x);
}
};
int main()
{
Int obj(3);
string str = obj;
obj = 20;
string str2 = static_cast<string>(obj);
obj = static_cast<Int>(30);
return 0;
}
Within the class there is not defined the assignment operator operator =( int ). But the class has the conversion constructor
Int(int x_in = 0)
So in this statement
obj = 20;
there is called the constructor like Int( 20 ) to convert the integer value to an object of the type Int that can be assigned to the object obj due to the implicit move assignment operator generated by the compiler.
Lacking a assignment operator taking int, your compiler uses the next best assignment operator it can get it's hands on, which is the implicitly declared move assignment operator (Int::operator=(Int&&)). To use this operator, a rvalue reference to a Int object is required, which the compiler creates using the constructor Int::Int(int), i.e. the compiler treats obj = 20; as
obj.operator=(Int(20));
To see what's happening here, you could implement the move assignment operator yourself to print something to the console when the assignment operator is executed:
class Int
{
...
public:
...
Int& operator=(Int&& other)
{
std::cout << "move assignment of Int, new value: " << other.x << '\n';
x = other.x;
return *this;
}
// the following members are only declared to make sure the available
// constructors/operators are the same as in the original version of the code
Int(Int&&) = default;
Int& operator=(Int const&) = default;
Int(Int const&) = default;
};
I want to make an operator= and copy constructor, to be called in the inherited class.
For normal objects, it works fine, but when I'm trying to call, for example, operator= with a pointer, it is just copying the object address.
So my question is, how can I call those methods with pointers?
#include <iostream>
// base class
class a {
public:
//constructors
a(): x(0), y(1), z(0){ std::cout << "no parameter constructor A\n"; }
a(int a, int b, int c) :x(a), y(b), z(c){ std::cout << "parameter constructor A\n"; }
a(const a& ob):x(ob.x), y(ob.y), z(ob.z)
{
std::cout << "copy constructor A\n";
}
//operator
a& operator=(const a& obj)
{
if (this != &obj)
{
x = obj.x;
y = obj.y;
z = obj.z;
}
std::cout << "operator = A\n";
return *this;
}
protected:
int x, y, z;
};
//child class
class b : public a
{
public:
//constructors
b() : p(0){ std::cout << "no parameter constructor B\n"; }
b(int X, int Y, int Z, int B) : a(X, Y, Z), p(B) { std::cout << "parameter constructor B\n"; }
b(const b& obj) :p(obj.p), a(obj)
{
std::cout << "copy constructor B\n";
}
//operator =
b& operator=(const b &obj)
{
if (this != &obj)
{
p = obj.p;
&a::operator=(obj);
}
std::cout << "operator = B\n";
return *this;
}
private:
int p;
};
int main()
{
b obj0(4, 8, 16, 32);
b obj1(obj0); // copy constructor
b obj2;
obj2 = obj1; // operator =
std::cout << std::endl << std::endl;
std::cout << "for pointers:\n\n";
a* obj3 = new b(4, 8, 16, 32);
a* obj4(obj3);
obj4 = obj3;
return 0;
}
One of the purposes of using pointers (or references) is to avoid needing to create a copy of the object. Passing a pointer to the object allows the receiver to refer to and manipulate on the original object.
If you wish the pointer to receive a new object, then you would use new.
When dealing with polymorphism as in your example, you would probably need a virtual method that creates a proper clone (sometimes called a deep copy).
class a {
//...
virtual a * clone () const = 0;
};
class b : public a {
//...
b * clone () const {
return new b(*this);
}
};
//...
a *obj4 = obj3->clone();
//...
We leverage that b * is a covariant return type for a *, so that b::clone() can return a b *, but a::clone() can use the b::clone() as an override and still return an a *.
What exactly happens at 1 & 2 internally , when we have assigned by return reference?
Class A
{
A& operator= (const A &ax)
{
return *this;
}
}
int main()
{
A a;
A b;
b = a; // -------------- 1
A c = a; // ----------- 2
}
// ---------------------------------------------------------------
What difference will happen in below (assigned returned value)? :
Class A
{
A operator= (const A &ax)
{
return *this;
}
}
int main()
{
A a;
A b;
b = a; // -------------- 3
A c = a; // ----------- 4
}
There is also principal mistake, because operator= made private and code is ill-formed, but this would be corrected by adding public: access modifiers.
operator= is invoked from object stored to b variable, so this variant of assignment should not perform assignment at all.
#include <iostream>
class A
{
public:
float a1;
A& operator= (const A &ax)
{
return *this;
}
};
int main()
{
A a;
a.a1 = 3;
A b;
b.a1 = 5;
b = a; // -------------- 1
std::cout << b.a1; // outputs 5
A c = a;
std::cout << c.a1; // outputs 3
}
The line
A c = a;
is called initialization and doesn't use operator=, instead it uses (generated by compiler) copy constructor, which does a shallow copy of object.
Your mistake is that member operator= meant to assign its argument's value to this. operator= return result of assignment, which can be used for chaining: a=b=c;
A& A::operator= (const A &right)
is equivalent of
A& operator= (A &left, const A &right)
I have the test code:
struct A
{
A (){}
A (const A & a)
{
std::cout<<"copy A";
}
};
int main()
{
A a;
const A& a1 = static_cast<A>(a);
return 0;
}
My question is why copy constructor is called?
UPD: added the description of class A.
Program output is: "copy A"