Copy constructor

I

I wish

I wrote some program

#include <iostream>
class A {
public:
A() {}
A( const A& t ) { std::cout << "Good" << std::endl; }
};

A f()
{
A t;
return t;
}

int main( void )
{
f();
return 0;
}

I think f() will invoke copy constructor at return t.

But it doesn't print anything, why?

--
|
___
(-_-)
<| |>---------------------------------- ShepJeng.twbbs.org -------------
/ cherry.cs.nccu.edu.tw
 
R

Russell Hanneken

I said:
I wrote some program

#include <iostream>
class A {
public:
A() {}
A( const A& t ) { std::cout << "Good" << std::endl; }
};

A f()
{
A t;
return t;
}

int main( void )
{
f();
return 0;
}

I think f() will invoke copy constructor at return t.

But it doesn't print anything, why?

Because the C++ standard gives compilers special permission to skip creating
a temporary object in a case like this. The local object just becomes the
returned object. In fact, you could even write

int main()
{
A var( f() );
}

and your compiler might never make a copy (the local object created in f
becomes var in main).

See http://tinyurl.com/37bhh
 
S

SaltPeter

I wish said:
I wrote some program

#include <iostream>
class A {
public:
A() {}
A( const A& t ) { std::cout << "Good" << std::endl; }
};

A f()
{
A t;
return t;
}

int main( void )
{
f();
return 0;
}

Why should the compiler copy by value an object of type A when the f()
discards it in main() above? Specifically, all the above code does is:

"call a function f() that constructs a temporary instance of A and discards
it"

Try:

int main()
{
A a = f();

return 0;
{

Also, to clarify whats happenning, and to emphasize that a copy constructor
is still a constructor, try:

class A
{
public:
A() { std::cout << "cstor" << std::endl; }
~A() { std::cout << "d~stor" << std::endl; }
A( const A& r_copy ) { std::cout << "copy cstor" << std::endl; }
};
I think f() will invoke copy constructor at return t.

no it won't, all f() was asked to do is create a temporary object. It can
only return by value if its given the opportunity to do so.
But it doesn't print anything, why?

--
|
___
(-_-)
<| |>----------------------------------
ShepJeng.twbbs.org -------------
 
R

Rolf Magnus

SaltPeter said:
Why should the compiler copy by value an object of type A when the f()
discards it in main() above? Specifically, all the above code does is:

"call a function f() that constructs a temporary instance of A and
discards it"

No. Function f() constructs a local instance of A and returns a copy of
it. Main() calls f() and then discards the returned value. The
important part is that main() is the one that discards the object, not
f().
The actual reason for the copy constructor not being called is probably
the return value optimization that allows the compiler to avoid copying
the object.
Try:

int main()
{
A a = f();

return 0;
{

That is likely to have the same effect. An optimizing compiler might let
main() specify the address of a to f(), so that f() can construct the
object directly into that memory instead of first constructing it in
its own local memory and then copying it.
Also, to clarify whats happenning, and to emphasize that a copy
constructor is still a constructor, try:

class A
{
public:
A() { std::cout << "cstor" << std::endl; }
~A() { std::cout << "d~stor" << std::endl; }
A( const A& r_copy ) { std::cout << "copy cstor" << std::endl; }
};


no it won't, all f() was asked to do is create a temporary object. It
can only return by value if its given the opportunity to do so.

And what makes you think this is not the case?
 
E

E. Robert Tisdale

Rolf said:
SaltPeter said:
Something said:
I wrote some program

#include <iostream>
class A {
public:
A(void) { }
A(const A& t) { std::cout << "Good" << std::endl; }
};

A f(void) {
A t;
return t;
}

int main(int argc, char* argv[]) {
f();
return 0;
}

Why should the compiler copy by value an object of type A when the f()
discards it in main() above? Specifically, all the above code does is:

"call a function f() that constructs a temporary instance of A and
discards it"

No.
Function f() constructs a local instance of A and returns a copy of it.

If it had called the copy constructor, it should have printed "Good"
but it didn't.
Function f(void) does *not* construct a local instance of A.
It recognized t as a reference to the return value
and initializes the return value directly.
No "local" object of type A is ever created or destroyed.
Main() calls f() and then discards the returned value.
The important part is that main() is the one that discards the object,
not f().

That's a vacuous remark because function main(int, char**)
discards *all* local objects when it returns.
The actual reason for the copy constructor not being called
is probably the return value optimization

Named Return Value Optimization (NRVO)
that allows the compiler to avoid copying the object.
Try:

int main(int argc, char* argv[]) {
A a = f();
return 0;
}

That is likely to have the same effect.
An optimizing compiler might let main() specify the address of a to f(),
so that f() can construct the object directly into that memory
instead of first constructing it in its own local memory
and then copying it.
Also, to clarify what's happenning, and to emphasize that a copy
constructor is still a constructor, try:


class A {
public:
A(void) { std::cout << "cstor" << std::endl; }
~A(void) { std::cout << "dstor" << std::endl; }
A(const A& r_copy) { std::cout << "copy cstor" << std::endl; }
};



No it won't. All f(void) was asked to do is create a temporary object.
It can only return by value if it's given the opportunity to do so.

And what makes you think this is not the case?

The typical implementation emits nearly identical code for

#include <iostream>
class A {
public:
A(void) { }
A(const A& t) { std::cout << "Good" << std::endl; }
};

extern "C" {
A& f(A& value) {
value = A();
return value;
}
}

and

#include <iostream>
class A {
public:
A(void) { }
A(const A& t) { std::cout << "Good" << std::endl; }
};

extern "C" {
A f(void) {
A t;
return t;
}
}

When the typical C++ compiler parses

A a = f();

it emits code to allocate automatic storage for a
then it passes a reference to a to f(void)
as a *hidden* argument -- f(a) --
and function f(A&) initializes a directly.
 
R

Rolf Magnus

E. Robert Tisdale said:
Rolf said:
SaltPeter said:
Something that calls itself I wish wrote:
I wrote some program

#include <iostream>
class A {
public:
A(void) { }
A(const A& t) { std::cout << "Good" << std::endl; }
};

A f(void) {
A t;
return t;
}

int main(int argc, char* argv[]) {
f();
return 0;
}

Why should the compiler copy by value an object of type A when the
f() discards it in main() above? Specifically, all the above code
does is:

"call a function f() that constructs a temporary instance of A and
discards it"

No.
Function f() constructs a local instance of A and returns a copy of
it.

If it had called the copy constructor, it should have printed "Good"
but it didn't.

Right, just like I wrote below. Please read postings completely before
you answer them.
Function f(void) does *not* construct a local instance of A.
....

That's the beginning of a function called f that creates a local
instance of A. If you don't agree, quote the part of the standard that
says it is not.
It recognized t as a reference to the return value
and initializes the return value directly.
No "local" object of type A is ever created or destroyed.

That's the optimization I wrote about.
That's a vacuous remark because function main(int, char**)
discards *all* local objects when it returns.

What are you talking about? I am talking about the return value of f,
but you seem to talk about something else.
Named Return Value Optimization (NRVO)

Which is just a special case of Return Value Optimization (RVO), AFAIK.
that allows the compiler to avoid copying the object.
Try:

int main(int argc, char* argv[]) {
A a = f();
return 0;
}

That is likely to have the same effect.
An optimizing compiler might let main() specify the address of a to
f(), so that f() can construct the object directly into that memory
instead of first constructing it in its own local memory
and then copying it.
[snip]

The typical implementation emits nearly identical code for

#include <iostream>
class A {
public:
A(void) { }
A(const A& t) { std::cout << "Good" << std::endl; }
};

extern "C" {
A& f(A& value) {
value = A();
return value;
}
}

and

#include <iostream>
class A {
public:
A(void) { }
A(const A& t) { std::cout << "Good" << std::endl; }
};

extern "C" {
A f(void) {
A t;
return t;
}
}

In which way is that not what I wrote above? I mean the only part of my
posting that you didn't comment. Why do you think you need to explain
something to me that I already know? The difference seems just that you
call it "the typical implementation", while I called it "an optimizing
compiler".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,430
Messages
2,571,676
Members
48,796
Latest member
Greg L.

Latest Threads

Top