473,387 Members | 1,721 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

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 1789
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

39
by: scooter | last post by:
Given this class heirarchy class Base{}; class A : public Base {}; class B : public Base {};
10
by: richardclay09 | last post by:
The output of this: #include <iostream> #include <vector> using namespace std; struct X { int i; X(const X& x) : i(x.i) { cout << "ctor copy: " << i << endl;
7
by: skishorev | last post by:
Hi, I know What is the copy constructor. I don't know where and why we have to use copy constructor. If You know please give to me with a situation where we have to use or with a small example....
10
by: dragoncoder | last post by:
Hi all, I am trying to understanding std::auto_ptr<Tclass implementation from "The C++ standard library" by Nicolai Josuttis. He gives a sample implementation of auto_ptr class template in...
3
by: John Salmon | last post by:
g++ complains about illegal access to a private member when the following is compiled with a private copy constructor for the class C. When the copy constructor is public, the program runs and...
10
by: campos | last post by:
"Effective C++ 3rd Edition" Item 6, P39 ------------------------------------------------------- class Uncopyable { protected: // allow construction Uncopyable() {} // and...
13
by: Jeroen | last post by:
Hi all, I'm trying to implement a certain class but I have problems regarding the copy ctor. I'll try to explain this as good as possible and show what I tried thusfar. Because it's not about a...
7
by: abhash | last post by:
I am bit puzzled at the following piece of code I tried: ---------------------------------------------------------------------------------- #include <iostream> using namespace std; class Test...
11
by: Dijkstra | last post by:
Hi folks! First, this is the code I'm using to expose the problem: ------------------------------------------------------------------ #include <functional> #include <string> #include...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.