consider the following program:
#include <iostream>
using namespace std;
class Test
{
public:
Test(int xx) : x(xx) { cout << x << endl; }
Test add(const Test & obj);
Test(const Test & obj) : x(obj.x)
{ cout << "copy ctor " << x << endl; }
int x;
};
Test Test::add(const Test & obj)
{
return x + obj.x;
}
int main()
{
Test a(10);
Test b(20);
cout << a.add(b).x << endl;
return 0;
}
This program compiles fine and produces the following output
in both g++ and VC++ Express Edition 2005
10
20
30
30
I thought the copy ctor would be called when we invoke a.add(b)
because Test::add() returns an object of Test type and here
I expected the copy ctor to be called.
I do not understand why the copy ctor is not called.
Is it optimized away ? Or this is the expected behaviour.
Kindly clarify.
Thanks
V.Subramanian 15 1696
On 11ÔÂ29ÈÕ, ÏÂÎç1ʱ52·Ö, "subramanian10...@yahoo.com, India"
<subramanian10...@yahoo.comwrote:
consider the following program:
#include <iostream>
using namespace std;
class Test
{
public:
Test(int xx) : x(xx) { cout << x << endl; }
Test add(const Test & obj);
Test(const Test & obj) : x(obj.x)
{ cout << "copy ctor " << x << endl; }
int x;
};
Test Test::add(const Test & obj)
{
return x + obj.x;
}
int main()
{
Test a(10);
Test b(20);
cout << a.add(b).x << endl;
return 0;
}
This program compiles fine and produces the following output
in both g++ and VC++ Express Edition 2005
10
20
30
30
I thought the copy ctor would be called when we invoke a.add(b)
because Test::add() returns an object of Test type and here
I expected the copy ctor to be called.
I do not understand why the copy ctor is not called.
Is it optimized away ? Or this is the expected behaviour.
Kindly clarify.
Thanks
V.Subramanian
your function add use referenece as argument. It does not create a new
temp object. So it does not call a copy constructor.
On 2007-11-29 00:52:25 -0500, "su**************@yahoo.com, India"
<su**************@yahoo.comsaid:
consider the following program:
#include <iostream>
using namespace std;
class Test
{
public:
Test(int xx) : x(xx) { cout << x << endl; }
Test add(const Test & obj);
Test(const Test & obj) : x(obj.x)
{ cout << "copy ctor " << x << endl; }
int x;
};
Test Test::add(const Test & obj)
{
return x + obj.x;
}
int main()
{
Test a(10);
Test b(20);
cout << a.add(b).x << endl;
return 0;
}
This program compiles fine and produces the following output
in both g++ and VC++ Express Edition 2005
10
20
30
30
I thought the copy ctor would be called when we invoke a.add(b)
because Test::add() returns an object of Test type and here
I expected the copy ctor to be called.
I do not understand why the copy ctor is not called.
Is it optimized away ? Or this is the expected behaviour.
Hmm... Interesting. Even the following code won't call the copy constructor:
void func()
{
Test a(10);
Test b = a.add(a); // I expected this line to invoke copy
ctor but didn't!
cout << b.x << endl;
}
And I added the destructor too:
~Test() { cout << "destroy " << x << endl; }
My output was this:
10
20
30
30
destroy 30
destroy 20
destroy 10
The behavior seems to be this: When you're copying from a temporary
object, it just does a bitwise copy and does not call the temporary
object's destructor.
FYI, I'm using g++ 4.0.1.
--
-kira
On 2007-11-29 01:34:49 -0500, Kira Yamato <ki*****@earthlink.netsaid:
On 2007-11-29 00:52:25 -0500, "su**************@yahoo.com, India"
<su**************@yahoo.comsaid:
>consider the following program:
#include <iostream>
using namespace std;
class Test { public: Test(int xx) : x(xx) { cout << x << endl; }
Test add(const Test & obj);
Test(const Test & obj) : x(obj.x) { cout << "copy ctor " << x << endl; }
int x; };
Test Test::add(const Test & obj) { return x + obj.x; }
int main() { Test a(10); Test b(20);
cout << a.add(b).x << endl;
return 0; }
This program compiles fine and produces the following output in both g++ and VC++ Express Edition 2005 10 20 30 30
I thought the copy ctor would be called when we invoke a.add(b) because Test::add() returns an object of Test type and here I expected the copy ctor to be called.
I do not understand why the copy ctor is not called. Is it optimized away ? Or this is the expected behaviour.
Hmm... Interesting. Even the following code won't call the copy constructor:
void func()
{
Test a(10);
Test b = a.add(a); // I expected this line to invoke copy
ctor but didn't!
cout << b.x << endl;
}
And I added the destructor too:
~Test() { cout << "destroy " << x << endl; }
My output was this:
10
20
30
30
destroy 30
destroy 20
destroy 10
The behavior seems to be this: When you're copying from a temporary
object, it just does a bitwise copy and does not call the temporary
object's destructor.
FYI, I'm using g++ 4.0.1.
Ok, I found this in the manpages for g++:
-fno-elide-constructors
The C++ standard allows an implementation to omit creating a tempo-
rary which is only used to initialize another object of the same
type. Specifying this option disables that optimization, and
forces G++ to call the copy constructor in all cases.
So, the answer is that it is a C++ standard behavior.
--
-kira
On Nov 28, 9:52 pm, "subramanian10...@yahoo.com, India"
<subramanian10...@yahoo.comwrote:
I thought the copy ctor would be called when we invoke a.add(b)
because Test::add() returns an object of Test type and here
I expected the copy ctor to be called.
A possible implementation strategy is that the calling function
reserves some space for the return object, and gives the function a
pointer to this space.
With these calling conventions, the function can construct the
returned object directly in that space.
I do not understand why the copy ctor is not called.
Is it optimized away ?
The temporary object is optimized away. No temporary object, therefore
no constructor. su**************@yahoo.com, India wrote:
consider the following program:
#include <iostream>
using namespace std;
class Test
{
public:
Test(int xx) : x(xx) { cout << x << endl; }
Test add(const Test & obj);
Test(const Test & obj) : x(obj.x)
{ cout << "copy ctor " << x << endl; }
int x;
};
Test Test::add(const Test & obj)
{
return x + obj.x;
}
int main()
{
Test a(10);
Test b(20);
cout << a.add(b).x << endl;
return 0;
}
This program compiles fine and produces the following output
in both g++ and VC++ Express Edition 2005
10
20
30
30
I thought the copy ctor would be called when we invoke a.add(b)
because Test::add() returns an object of Test type and here
I expected the copy ctor to be called.
The compiler is free to optimise away the temporary return object (so
long as doing so doesn't change the behaviour of the program).
--
Ian Collins.
Ian Collins wrote:
>... I thought the copy ctor would be called when we invoke a.add(b) because Test::add() returns an object of Test type and here I expected the copy ctor to be called.
The compiler is free to optimise away the temporary return object (so
long as doing so doesn't change the behaviour of the program).
In fact, the compiler is free to optimize away the temporary return object even
if it _does_ change the behavior of the program.
--
Best regards,
Andrey Tarasevich su**************@yahoo.com, India wrote:
Test Test::add(const Test & obj)
{
return x + obj.x;
}
I thought the copy ctor would be called when we invoke a.add(b)
because Test::add() returns an object of Test type and here
I expected the copy ctor to be called.
Return value optimization. This is a very common optimization
performed by compilers when the return value of a function is an object.
Basically, what is happening internally is that the calling code gives,
behind the scenes, the function a pointer which basically says
"construct the return value here". Then the function, instead of
creating a local copy for the return value, constructs it directly to
the memory location which was given to it by the calling code.
IOW, if you say for example "Test t = a.add(b);" this will make the
compiler to create space for 't' and give a pointer to Test::add() so
that it can construct the return value into that space directly, thus
avoiding copying anything.
Note that the avoiding the copying is not always possible. For example
in this case the copying usually must be performed:
"extern Test t; t = a.add(b);"
What the compiler does in this case is to create a nameless temporary,
tell the function to construct the return value there, and then it
assigns this temporary to 't'.
Andrey Tarasevich wrote:
Ian Collins wrote:
>>... I thought the copy ctor would be called when we invoke a.add(b) because Test::add() returns an object of Test type and here I expected the copy ctor to be called.
The compiler is free to optimise away the temporary return object (so long as doing so doesn't change the behaviour of the program).
In fact, the compiler is free to optimize away the temporary return object
even if it _does_ change the behavior of the program.
Which is the reason why the OP didn't see any output from the copy
constructor. The 'missing' output is a change in behavior.
On Nov 29, 8:33 am, Juha Nieminen <nos...@thanks.invalidwrote:
subramanian10...@yahoo.com, India wrote:
Test Test::add(const Test & obj)
{
return x + obj.x;
}
I thought the copy ctor would be called when we invoke a.add(b)
because Test::add() returns an object of Test type and here
I expected the copy ctor to be called.
Return value optimization. This is a very common optimization
performed by compilers when the return value of a function is an object.
Basically, what is happening internally is that the calling code gives,
behind the scenes, the function a pointer which basically says
"construct the return value here". Then the function, instead of
creating a local copy for the return value, constructs it directly to
the memory location which was given to it by the calling code.
IOW, if you say for example "Test t = a.add(b);" this will make the
compiler to create space for 't' and give a pointer to Test::add() so
that it can construct the return value into that space directly, thus
avoiding copying anything.
Note that the avoiding the copying is not always possible. For example
in this case the copying usually must be performed:
"extern Test t; t = a.add(b);"
What the compiler does in this case is to create a nameless temporary,
tell the function to construct the return value there, and then it
assigns this temporary to 't'.
Do you mean to say, in the statement,
t = a.add(b);
copy ctor will be called first to create the temporary and then the
assignment operator will be called ?
If this is what you meant, then I have to say that it does not happen
with
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
ie the copy ctor is not called to create the temporary.
Please correct me if I am wrong.
Thanks
V.Subramanian
On Nov 29, 6:33 pm, Juha Nieminen <nos...@thanks.invalidwrote:
subramanian10...@yahoo.com, India wrote:
Test Test::add(const Test & obj)
{
return x + obj.x;
}
I thought the copy ctor would be called when we invoke a.add(b)
because Test::add() returns an object of Test type and here
I expected the copy ctor to be called.
Return value optimization. This is a very common optimization
performed by compilers when the return value of a function is an object.
Basically, what is happening internally is that the calling code gives,
behind the scenes, the function a pointer which basically says
"construct the return value here". Then the function, instead of
creating a local copy for the return value, constructs it directly to
the memory location which was given to it by the calling code.
IOW, if you say for example "Test t = a.add(b);" this will make the
compiler to create space for 't' and give a pointer to Test::add() so
that it can construct the return value into that space directly, thus
avoiding copying anything.
Note that the avoiding the copying is not always possible. For example
in this case the copying usually must be performed:
"extern Test t; t = a.add(b);"
What the compiler does in this case is to create a nameless temporary,
tell the function to construct the return value there, and then it
assigns this temporary to 't'.
Do you mean to say, in the statement,
t = a.add(b);
copy ctor will be called first to create the temporary and then the
assignment operator will be called ?
If this is what you meant, then I have to say that it does not happen
with
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
ie the copy ctor is not called to create the temporary.
Please correct me if I am wrong.
Thanks
V.Subramanian su**************@yahoo.com, India wrote:
On Nov 29, 8:33 am, Juha Nieminen <nos...@thanks.invalidwrote:
>subramanian10...@yahoo.com, India wrote:
>>Test Test::add(const Test & obj) { return x + obj.x; } I thought the copy ctor would be called when we invoke a.add(b) because Test::add() returns an object of Test type and here I expected the copy ctor to be called.
Return value optimization. This is a very common optimization performed by compilers when the return value of a function is an object. Basically, what is happening internally is that the calling code gives, behind the scenes, the function a pointer which basically says "construct the return value here". Then the function, instead of creating a local copy for the return value, constructs it directly to the memory location which was given to it by the calling code.
IOW, if you say for example "Test t = a.add(b);" this will make the compiler to create space for 't' and give a pointer to Test::add() so that it can construct the return value into that space directly, thus avoiding copying anything.
Note that the avoiding the copying is not always possible. For example in this case the copying usually must be performed: "extern Test t; t = a.add(b);" What the compiler does in this case is to create a nameless temporary, tell the function to construct the return value there, and then it assigns this temporary to 't'.
Do you mean to say, in the statement,
t = a.add(b);
copy ctor will be called first to create the temporary and then the
assignment operator will be called ?
A temporary isn't required, the compiler can assign a to t.
--
Ian Collins.
On 2007-11-29 23:04:42 -0500, "su**************@yahoo.com, India"
<su**************@yahoo.comsaid:
On Nov 29, 8:33 am, Juha Nieminen <nos...@thanks.invalidwrote:
>subramanian10...@yahoo.com, India wrote:
>>Test Test::add(const Test & obj) { return x + obj.x; } I thought the copy ctor would be called when we invoke a.add(b) because Test::add() returns an object of Test type and here I expected the copy ctor to be called.
Return value optimization. This is a very common optimization performed by compilers when the return value of a function is an object. Basically, what is happening internally is that the calling code gives, behind the scenes, the function a pointer which basically says "construct the return value here". Then the function, instead of creating a local copy for the return value, constructs it directly to the memory location which was given to it by the calling code.
IOW, if you say for example "Test t = a.add(b);" this will make the compiler to create space for 't' and give a pointer to Test::add() so that it can construct the return value into that space directly, thus avoiding copying anything.
Note that the avoiding the copying is not always possible. For example in this case the copying usually must be performed: "extern Test t; t = a.add(b);" What the compiler does in this case is to create a nameless temporary, tell the function to construct the return value there, and then it assigns this temporary to 't'.
Do you mean to say, in the statement,
t = a.add(b);
copy ctor will be called first to create the temporary and then the
assignment operator will be called ?
If this is what you meant, then I have to say that it does not happen
with
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
ie the copy ctor is not called to create the temporary.
Please correct me if I am wrong.
This is what is going on. Consider the code
Test t = a.add(b);
Normally, you would think the compiler would do the following:
1) Create a local variable t in the caller function.
2) Call a.add(b), which will create a temporary variable as the result.
3) Call the copy constructor to copy the content in the temporary
variable returned by add() into the local variable t.
4) Call the temporary variable's destructor at the end of the statement.
However, with optimization, this is what the compiler will actually do instead:
a) Call a.add(b), which will create a temporary variable as the result.
b) Have the variable t be referencing the location of the temporary
variable above. No object destructor is called at the end of the
statement. No local variable is created in the stack frame of the
caller function.
Here is proof: With the following code,
#include <iostream>
using namespace std;
class Test
{
public:
Test(int xx) : x(xx) { cout << x << endl; }
Test add(const Test & obj);
Test(const Test & obj) : x(obj.x)
{ cout << "copy ctor " << x << endl; }
~Test()
{ cout << "destroy " << x << endl; }
int x;
};
Test Test::add(const Test & obj)
{
Test y(x + obj.x);
cout << "Test::add(). &y=" << &y << endl;
return y;
}
int main()
{
Test a = Test(10);
Test b = a.add(a);
cout << "main(). &b=" << &b << endl;
return 0;
}
=====================
The output of this code is:
10
20
Test::add(). &y=0xbffff8fc
main(). &b=0xbffff8fc
destroy 20
destroy 10
=====================
Note that the addresses of y and b are the same.
--
-kira
On Nov 30, 6:12 am, Ian Collins <ian-n...@hotmail.comwrote:
subramanian10...@yahoo.com, India wrote:
On Nov 29, 8:33 am, Juha Nieminen <nos...@thanks.invalidwrote:
subramanian10...@yahoo.com, India wrote: Test Test::add(const Test & obj) { return x + obj.x; } I thought the copy ctor would be called when we invoke a.add(b) because Test::add() returns an object of Test type and here I expected the copy ctor to be called.
Return value optimization. This is a very common optimization
performed by compilers when the return value of a function is an object..
Basically, what is happening internally is that the calling code gives,
behind the scenes, the function a pointer which basically says
"construct the return value here". Then the function, instead of
creating a local copy for the return value, constructs it directly to
the memory location which was given to it by the calling code.
IOW, if you say for example "Test t = a.add(b);" this will make the
compiler to create space for 't' and give a pointer to Test::add() so
that it can construct the return value into that space directly, thus
avoiding copying anything.
Note that the avoiding the copying is not always possible. For example
in this case the copying usually must be performed:
"extern Test t; t = a.add(b);"
What the compiler does in this case is to create a nameless temporary,
tell the function to construct the return value there, and then it
assigns this temporary to 't'.
Do you mean to say, in the statement,
t = a.add(b);
copy ctor will be called first to create the temporary and then the
assignment operator will be called ?
A temporary isn't required, the compiler can assign a to t.
I certainly hope not. The formal semantics here are clear:
the return statement constructs a return value by implicitly
converting the results of x + obj.x to a (temporary) Test,
that temporary is copied to whatever location is used for
value return (which is also a temporary), and
the const reference parameter of the assignment operator is
bound to that returned value.
The compiler is allowed to suppress the copy, and construct the
temporary in the return statement directly in its final
location. But it definitly needs a temporary to bind to the
reference in the assignment operator.
The compiler cannot assign a to t, since the return value of
Test::add is not a copy of a.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 su**************@yahoo.com, India wrote:
Do you mean to say, in the statement,
t = a.add(b);
copy ctor will be called first to create the temporary and then the
assignment operator will be called ?
Not really. With "copying" I was referring to the assignment.
There are probably similar ways to "force" a true copy constructor
call even when return value optimization is in use. This discussion thread is closed Replies have been disabled for this discussion. Similar topics
39 posts
views
Thread by scooter |
last post: by
|
10 posts
views
Thread by richardclay09 |
last post: by
|
7 posts
views
Thread by skishorev |
last post: by
|
10 posts
views
Thread by dragoncoder |
last post: by
|
3 posts
views
Thread by John Salmon |
last post: by
|
10 posts
views
Thread by campos |
last post: by
|
13 posts
views
Thread by Jeroen |
last post: by
|
7 posts
views
Thread by abhash |
last post: by
|
11 posts
views
Thread by Dijkstra |
last post: by
| | | | | | | | | | |