This question already has answers here:
Why copy constructor is not called here?
(2 answers)
Closed 8 years ago.
I have the following code:
#include <iostream>
using namespace std;
class X
{
public:
int g;
X() { cout << "constr" << endl; }
X(const X& ref1) { cout << "copy constr" << endl; }
};
X f()
{
X ee;
ee.g = 1;
return ee;
}
int main()
{
X ff = f();
return 0;
}
Running the code I see that the constructor was called only once and the copy constructor was never called. Don't you expect two constructor and one copy constructor calls here? Thanks!
This is a special case of the copy elision called return value optimization (the link explains precisely your case).
Copy Elision is an optimization implemented by many compilers to prevent extra, unnecessary, copies. Makes the return-by-value or pass-by-value possible in practice.
Take a look at the example in the following answer: https://stackoverflow.com/a/12953129/1938163
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Hello World!\n";
C obj = f();
}
(http://en.wikipedia.org/wiki/Return_value_optimization#Summary)
Perhaps incredible to believe the first time, depending on the compiler & settings, the following outputs are all valid:
Hello World!
A copy was made.
A copy was made.
Hello World!
A copy was made.
Hello World!
In your case, this is a special copy elision optimization called RVO - Return Value Optimization where an object returned by value from a method has its copy elided.
Related
I read about copy elision and how it can fasten up Programms by giving possibilities to write code more straight foreword without thinking about references of variables.
In a small example I tried to find the limits of this technique.
#include <iostream>
class A
{
public:
A(){}
A(const A &a) {std::cout << "Copy" << std::endl;}
};
A foo(A a)
{
return a;
}
int main(void)
{
A a = foo(foo(A()));
std::cout << std::endl;
A b;
b = foo(foo(b));
return 0;
}
https://godbolt.org/z/xo88jq
Output:
Copy
Copy
Copy
Copy
Copy
The compiler already elides many of the copies in this example.
But why is the compiler not able to elide all those copies leading to a or in the modification of b?
This question already has answers here:
What are copy elision and return value optimization?
(5 answers)
Closed 7 years ago.
I wrote this:
#include <iostream>
struct A
{
int a;
int b;
A() : a(10) { std::cout << "default ctor" << std::endl;}
~A(){ }
A(const A&){ std::cout << "copy ctor" << std::endl; }
A(const A&&){ std::cout << "move ctor" << std::endl; }
};
A init()
{
A a;
a.b = 20;
return a;
}
int main()
{
A a = init();
std::cout << a.b << std::endl;
}
I expected that A a = init() imposes the move-contructor call, but the outpur is:
default ctor
20
DEMO
The line
A a = init();
is inlined by NRVO. It creates an object by using it's default constructor in its segment of code:
A a;
Your move constructor will not be used here.
The move constructor here can be used with -fno-elide-constructors compiler flag. I've modified your example to compile it with this flag. But note, that default constructor will always be called because NRVO does not affect this in your code. NRVO only means that the object will be constructed in the storage that it is needed (not on the stack of your init method) so it would not be moved or copied. With the no-elide flag it can't be created there so it would be copied/moved there.
This question already has answers here:
What are copy elision and return value optimization?
(5 answers)
Closed 7 years ago.
I am trying to understand the concept of copy constructors in C++. I have written the following program:
#include<iostream>
using namespace std;
class Box{
private:
int d;
public:
Box(int i){
cout << "Constructor" << endl;
d = i;
}
Box(const Box &old){
cout << "Copy Constructor" << endl;
d = old.d;
}
int getd(){
return d;
}
~Box(){
cout << "Destructor" << endl;
}
Box operator+(const Box& op){
Box c(15);
c.d = d + op.d;
return c;
}
};
int main(){
Box a(10);
Box b = a;
Box c = a+b;
cout << c.getd() << endl;
return 0;
}
The output of this program is as follows:
Constructor
Copy Constructor
Constructor
20
Destructor
Destructor
Destructor
I don't understand why the copy constructor isn't getting called for the third line in the main function. I think that there should be a call to the copy constructor as operator+ function returns by value.
The compiler is optimising out the copy constructor call here, because the standard explicitly allows that copy to be "elided". What would be the point in such a copy, really?
You're absolutely right though, in that it's an opportunity for invocation of the copy constructor, and the compiler could do it. In fact, the standard does require that invoking the copy constructor be valid here.
#include <iostream>
struct A
{
A() { std::cout << "Def Constr\n"; }
A(const A&) { std::cout << "Copy Constr\n"; }
};
A func1()
{
return A{};
}
void func2(A a) {}
int main()
{
func2(func1());
}
After compiling with
g++ Copy.cpp -std=c++11 -fno-elide-constructors
Output is :
Def Constr
Copy Constr
Copy Constr
And my questions is : Why 2 Copy Constr ? I thought only 1 Copy was needed.
I might have a guess that func1() throws a temp object and this temp object needs to be copied to another memory region and from that region again a copy must be made for the func2() parameter but it's vague for me .
Could you explain it in detail please ?
The return value of func1 is copied from the expression A{}.
The value of the function call expression func1() is copied into the function parameter of func2.
Yes your understanding is right. Your line of code (without copy eliding) is similar to
int main()
{
{
A temp = func1(); // 2nd copy
func2(temp); // 3rd copy
}
}
I encountered a code snippet and thought that it would call copy-constructor but in contrast , it simply called normal constructor . Below is the code
#include <iostream>
using namespace std;
class B
{
public:
B(const char* str = "\0")
{
cout << "Constructor called" << endl;
}
B(const B &b)
{
cout << "Copy constructor called" << endl;
}
};
int main()
{
B ob = "copy me";
return 0;
}
What you've discovered that B ob = "copy me"; notionally creates a B from the literal and then copy constructs ob, but that the compiler is allowed to elide the copy and construct directory into ob. g++ even elides the copy with no optimization enabled at all.
You can observe that this is the case by making your copy constructor private: The code will fail to compile even though the compiler won't actually use the copy constructor (the standard requires that copy constructors be accessible even when the call is elided).