Why copy constructor is called? - c++

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"

Related

c++ missing construction and destruction of an object

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.

copy constructor, operator= in a child class

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 *.

A copy constructor call

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

assignments operator between father and son

I have the next classes.
in the main I have 2 kinds of assignments operator (A=A and B=B).
I'm trying to get the main working, so I tried:
class A { // assume that this class is abstract
public:
virtual void assignment(const A& num) = 0;
void operator=(const A& num) { assignment(num); }
void func() = 0; // the class is abstract
};
class B: public A {
int i;
public:
void assignment(const B& num) { i = num.i; }
B& operator=(const B& num) { i = num.i; }
void func() { cout << "hello!\n"; }
};
int main()
A* a1 = new B(7); //assume I have it
A* a2 = new B(6); //assume I have it
B b1(2);
B b2(4);
*a1 = *a2; // implement an assignment operator
b1 = b2; // implement an assignment operator
}
but I got some errors that tell me that B is an abstract class and then the copy constructor doesn't work
any help appreciated!
Ok, now I see what the problem is:
void assignment(const B& num) { i = num.i; }
should be:
void assignment(const A& num) { ... }
However, we now have a problem: num which is of type A does not have a member variable i. So we need to ensure that num is actually of class B. The ... part in the above now turns into:
B& b_num = dynamic_cast<B&>(num);
i = num.i;
Note however that dynamic_cast may throw an exception if you are trying to convert some other type to B& than B.

local classes c-ism

Only first pair of values output on running this program seem correct, the others don't. What is going on?
#include <iostream>
#include <vector>
class a
{
public:
class b
{
public:
a* parent;
void test()
{
std::cout<<parent->value<<std::endl;
}
} b1;
unsigned long value;
a()
{
b1.parent = this;
value = 2;
}
void go()
{
value++;
b1.test();
}
};
int main()
{
{
a a1;
a1.go();
std::cout<<a1.value<<std::endl;
}
std::cout<<std::endl;
{
a a1; a1 = a();
a1.go();
std::cout<<a1.value<<std::endl;
}
std::cout<<std::endl;
{
std::vector<a> a1; a1.push_back(a());
a1.at(0).go();
std::cout<<a1.at(0).value<<std::endl;
}
return 0;
}
You are missing a copy ctor and assignment operator for type 'a'. When copying or assigning objects, you consequently don't properly update their b1.parent. Instead, the b1.parent values point to a different 'a' object than their real parent.
To see this problem in action, use this in your existing code:
void go() {
value++;
std::cout << (this == b1.parent ? "as expected\n" : "uh-oh\n");
b1.test();
}
To fix it, modify class a:
a() : b1 (this), value (2) {} // a change from your default ctor
a(a const &x) : b1 (this), value (x.value) {}
a& operator=(a const &x) {
value = x.value;
return *this;
}
And modify class b (necessarily to use the ctor initializer as I do above):
b(a *parent) : parent (parent) {}