C++ Constructor calling [duplicate] - c++

This question already has answers here:
Why does assignment operator call constructor?
(4 answers)
Closed 2 years ago.
Lets assume I have a program:
class A {
public:
A() { cout << '1'; }
A(int i) { cout << '2'; }
};
int main() {
A a;
a = 0;
return 0;
}
Result of this program will be 12.
So my question is - why am I able to call the second constructor through a = 0, when I already created the object and called the first constructor. I don't understand the whole concept of this. Isn't a constructor supposed to be called only once (during object creation)?

Isn't a constructor supposed to be called only once (during object creation)?
Yes, and that's what happens.
When you do a = 0;, the copy assignment operator A &operator=(const A &) gets called. Since the second operand is an int rather than an A, a new temporary instance of A is constructed, passed to the assignment operator, and then is destroyed right after it finishes.

The A(int) constructor allows implicit conversion from int to A.
So what happens with:
a = 0;
is really:
a = A(0);
If you want to disallow such implicit conversions, you need to make the constructor explicit:
explicit A(int);

This type of constructor is called "conversion constructor".
These type of constructors are used to perform implicit class-type conversions in C++.
Here you can find a little doc if you want to read.

Related

Why does my rvalue copy constructor not work? [duplicate]

This question already has answers here:
What are copy elision and return value optimization?
(5 answers)
Closed 5 years ago.
I was testing my knowledge in C++ and have encountered a problem. Consider this code:
class A
{
public:
A(int n = 0)
: m_n(n)
{
std::cout << 'd';
}
A(const A& a)
: m_n(a.m_n)
{
std::cout << 'c';
}
A(A&& a){
std::cout<<'r';
}
private:
int m_n;
};
int main()
{
A a = A();
std::cout << std::endl;
return 0;
}
Clearly, the A() constructor is an rvalue, as no permanent object has been created. So I think that first I have to see "d" as output. Then we are copying the rvalue to our new object, which is yet to be initialised. I have implemented a copy constructor that accepts an rvalue as an argument but I did not see the proof (no "r" output).
Can someone explain why that is?
You're seeing a form of copy elision -- the compiler is actually required to optimize and implement A a = A() by initializing a directly with the arguments to the constructor expression (() in this case) rather than creating a temporary and copying it into a. If you want to enforce an unnamed object to be copied, you need to initialize a with an expression that is not a simple constructor call.
Note that even then, the compiler may elide construtor calls by the as-if rule (if the only visible side effects are in the copy/move constructors/destructors. Your best bet to "force" a call to the move ctor is to use a named value and std::move:
A a1;
A a2 = std::move(a1);

Why copy-constructor is not called but default constructor is invoked in this code? [duplicate]

This question already has answers here:
Why is the copy constructor not called?
(4 answers)
Closed 9 years ago.
I have an understanding that copy constructor will be called when an object is created from an already existing object and also when a function returns object by value. So why in the below code the copy constructor is not called but the default constructor?
class A {
public:
A() { cout << "A" << endl; }
A(A &) { cout << "A&" << endl; }
A(const A &) { cout << "const A&" << endl; }
};
A fun() {
class A a;
return a;
}
int main() {
class A a = fun(); // output: A
}
Short answer: compiler optimizations.
First, the a object from your function is created directly in the scope of the main function, in order to avoid having to copy (or move in C++11) the local parameter out of the scope of the function via the function's return. This is return value optimization.
Then, in main, the statement becomes equivalent to class A a = A() and again the compiler is allowed to the create the a object in place, without copying from a temporary object. This is copy elision.
This is allowed even if the copy constructor (which is bypassed entirely) has side-effects, like in your example.

C++ copy constructor compilation error [duplicate]

This question already has answers here:
Why copy constructor not invoked here
(2 answers)
Closed 8 years ago.
I have read some articles concerning this topic but still have problems to compile my own code.
I have class A:
class A
{
public:
List<int> data;
A(){}
A(A&){}
A& operator= (const A& a)
{
// copy the data from a to data
}
};
Class B will call class A:
class B
{
public:
A makeA()
{
A a;
return a;
}
A getA()
{
A a = makeA();
return a;
}
};
When I compile my code with g++ under Linux, I got:
no matching function for call to 'A::A(A)'.
It seems that the compiler has simply ignored the assignment operation. Can you help me out of this?
In order for this to compile, your copy constructor must take its parameter by const reference:
A(const A&){}
Adding const to your constructor signature fixes this problem (demo on ideone).
Since you are defining an assignment operator and a copy constructor, you should strongly consider adding a desctructor ~A() (see the Rule of Three).
The assignment operator is not used here.
A a = makeA();
This line is an initialization; it uses the copy constructor to copy the value returned by makeA into a. The compiler is complaining because A::A(A&) can't be used with a temporary; change it to the much more common form A(const A&) and things will be much better.
#Peter is right. The copy constructor A(A&){} wants to be A(const A&){}, instead. The reason is that A(A&){} tells the compiler to prepare to modify the A passed to the copy constructor, which does not really make sense, and certainly does not make sense in case the A you pass is a temporary.

Copy Constructor is not invoked [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why copy constructor is not called in this case?
Consider the sample program below:
#include <iostream>
using namespace std;
class sample
{
private:
int x;
public:
sample(int a=0) : x(a)
{
cout << "default ctor invoked\n";
}
sample(const sample& obj)
{
cout << "copy ctor invoked\n";
}
};
int main()
{
sample s2 = sample(20); //Line1
sample s3 = 20; //Line2
return 0;
}
In Line1, first the constructor of sample class is invoked explicitly with the argument 20. Then i expected the copy constructor to be invoked to initialize s2.
In Line2, first the constructor of sample class is invoked implicitly first with the argument 20. Here also i expected the copy constructor to be invoked to initialize s2.
In both cases, the copy constructor is not invoked? Why is this happening? I believe, there is something wrong with my understanding of the invocation of copy constructor. Could someone correct me where i am going wrong?
This is expected. It's called copy elision.
Your expectation is correct, but they made an exception in C++ (for performance) which allows the compiler to treat your expression as direct initialization of one instance while bypassing the copy constructor.
in first line it does not invoke copy constructor because you do not copy an object. You are assigning one object to other. C++ provide default = operator which perform shallow copy. And this is invoked implicitly. The constructor is called for right hand object and default constructor is invoked for the left hand object. After that default = operator is invoked.
For line 2, it use constructor that takes int parameters that you define. It is actually converter constructor because it takes an integer and creates object of your class. Thats why c++ use this as a converter constructor and when you try to assign an integer to your object, c++ invokes inplicitly this converter constructor.
I hope this helps you to understand.

C++ constructor syntax [duplicate]

This question already has answers here:
Is there a difference between copy initialization and direct initialization?
(9 answers)
Closed 1 year ago.
Simple question: are the following statements equivalent? or is the second one doing more implicit things behind the scenes (if so, what?)
myClass x(3);
myClass x = myClass(3);
Thanks!
They are not completely identical. The first is called "direct initialization" while the second is called "copy initialization".
Now, the Standard makes up two rules. The first is for direct initialization and for copy initialization where the initializer is of the type of the initialized object. The second rule is for copy initialization in other cases.
So, from that point of view both are termed in one - the first - rule. In the case where you have copy initialization with the same type, the compiler is allowed to elide a copy, so it can construct the temporary you create directly into the initialized object. So you can end up very well with the same code generated. But the copy constructor, even if the copy is elided (optimized out), must still be available. I.e if you have a private copy constructor, that code is invalid if the code in which it appears has no access to it.
The second is called copy-initialization, because if the type of the initializer is of a different type, a temporary object is created in trying to implicitly convert the right side to the left side:
myclass c = 3;
The compiler creates a temporary object of the type of myclass then when there is a constructor that takes an int. Then it initializes the object with that temporary. Also in this case, the temporary created can be created directly in the initialized object. You can follow these steps by printing messages in constructors / destructors of your class and using the option -fno-elide-constructors for GCC. It does not try to elide copies then.
On a side-note, that code above has nothing to do with an assignment operator. In both cases, what happens is an initialization.
The second one may or may not call for an extra myclass object construction if copy elision is not implemented by your compiler. However, most constructors, have copy elision turned on by default even without any optimization switch.
Note initialization while construction never ever calls the assignment operator.
Always, keep in mind:
assignment: an already present object gets a new value
initialization: a new object gets a value at the moment it is born.
In the second one, a temporary object is created first and then is copied into the object x using myClass's copy constructor. Hence both are not the same.
I wrote the following to try and illustrate understand what's going on:
#include <iostream>
using namespace std;
class myClass
{
public:
myClass(int x)
{
this -> x = x;
cout << "int constructor called with value x = " << x << endl;
}
myClass(const myClass& mc)
{
cout << "copy constructor called with value = " << mc.x << endl;
x = mc.x;
}
myClass & operator = (const myClass & that)
{
cout << "assignment called" << endl;
if(this != &that)
{
x = that.x;
}
return *this;
}
private:
int x;
};
int main()
{
myClass x(3);
myClass y = myClass(3);
}
When I compile and run this code I get the following output:
$ ./a.out
int constructor called with value x = 3
int constructor called with value x = 3
This would seem to indicate that there is no difference between the two calls made in the main function, but that would be wrong. As litb pointed out, the copy constructor must be available for this code to work, even though it gets elided in this case. To prove that, just move the copy constructor in the code above to the private section of the class definition. You should see the following error:
$ g++ myClass.cpp
myClass.cpp: In function ‘int main()’:
myClass.cpp:27: error: ‘myClass::myClass(const myClass&)’ is private
myClass.cpp:37: error: within this context
Also note that the assignment operator is never called.