469,612 Members | 2,644 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,612 developers. It's quick & easy.

why copy ctor not called

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
Nov 29 '07 #1
15 1614
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.
Nov 29 '07 #2
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

Nov 29 '07 #3
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

Nov 29 '07 #4
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.
Nov 29 '07 #5
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.
Nov 29 '07 #6
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
Nov 29 '07 #7
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'.
Nov 29 '07 #8
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.

Nov 29 '07 #9
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
Nov 30 '07 #10
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
Nov 30 '07 #11
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.
Nov 30 '07 #12
su**************@yahoo.com, India wrote:
>
Please correct me if I am wrong.
You asked the same same thing twice!

--
Ian Collins.
Nov 30 '07 #13
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

Nov 30 '07 #14
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閑 objet/
Beratung in objektorientierter Datenverarbeitung
9 place S閙ard, 78210 St.-Cyr-l'蒫ole, France, +33 (0)1 30 23 00 34
Nov 30 '07 #15
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.
Nov 30 '07 #16

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
reply views Thread by devrayhaan | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.