Return object question

M

MathWizard

Hi,

I have a question about returning an object in a function and calling a
copy constructor. As far as I understand, in the following code the copy
constructor may or may not be called, depending on the compiler:

A what()
{
A my_A;
// do something with A.
return A;
}

Suppose I have also a class B and a constructor for A from B:

A::A(const B& b);

The question is now about the following code:

A what()
{
B my_B;
// do something with B.
return B;
}

As far as I can see, the constructor 'A::A(const B& b)' must be called
in order to return an object A. But is it possible that after that
constructor some (stupid) compiler decides that the copy constructor for
A must be called also? Maybe some compiler might think that the copy
constructor must be called always if an object must be returned...

Thansk for any answers,

Jeroen
 
D

David Harmon

On Sat, 21 Apr 2007 21:53:12 +0200 in comp.lang.c++, MathWizard
As far as I can see, the constructor 'A::A(const B& b)' must be called
in order to return an object A. But is it possible that after that
constructor some (stupid) compiler decides that the copy constructor for
A must be called also?

Yes, it is completely expected if your compiler is a little bit simple.
A compiler smart enough to skip it is doing "return value optimization".
The smart compiler is still required to check that the copy constructor
is accessible and give you an error if not, even though it's not called.
 
J

James Kanze

I have a question about returning an object in a function and calling a
copy constructor. As far as I understand, in the following code the copy
constructor may or may not be called, depending on the compiler:
A what()
{
A my_A;
// do something with A.
return A;
}

Correct. Technically, the semantics specified by the standard
require that the copy constructor be called, but the standard
then gives the compiler explicit authorization to merge my_A and
the return value, and not call the copy constructor. (Note that
while not calling the copy constructor is the most visible
effect, there are others as well.) This is called NRVO: Named
Return Value Optimization.
Suppose I have also a class B and a constructor for A from B:

A::A(const B& b);
The question is now about the following code:
A what()
{
B my_B;
// do something with B.
return B;
}
As far as I can see, the constructor 'A::A(const B& b)' must be called
in order to return an object A. But is it possible that after that
constructor some (stupid) compiler decides that the copy constructor for
A must be called also?

The formal semantics are almost the same as above: first you
construct a temporary of type A, then you copy it into the
return value. Again, the standard explicitly allows the
compiler to elide the copy.
Maybe some compiler might think that the copy
constructor must be called always if an object must be returned...

The copy constructor must be callable in both cases, or the code
is illegal. But I think that most compilers today elide the
copy in both cases.
 
J

Jeroen

James Kanze schreef:
Correct. Technically, the semantics specified by the standard
require that the copy constructor be called, but the standard
then gives the compiler explicit authorization to merge my_A and
the return value, and not call the copy constructor. (Note that
while not calling the copy constructor is the most visible
effect, there are others as well.) This is called NRVO: Named
Return Value Optimization.





The formal semantics are almost the same as above: first you
construct a temporary of type A, then you copy it into the
return value. Again, the standard explicitly allows the
compiler to elide the copy.


The copy constructor must be callable in both cases, or the code
is illegal. But I think that most compilers today elide the
copy in both cases.

--
James Kanze (Gabi Software) email: (e-mail address removed)
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

OK, thanks for the answer James. But it looks like I'm stuck with my
'solution'. The thing is, I have a function which was originally
implemented as:

A special_function()
{
A my_A;
// do something with A.
return A;
}

I call it 'special_function' here, because here, if the copy constructor
is called, the copy constructor must do something different than in all
other cases when the copy constructor for 'A' is called.

So I wanted to make a solution with:

A special_function()
{
B my_B;
// do something with B.
return B;
}

so that I could force to use the constructor from B to A and thus
implement the slightly different behaviour for returning from
'special_function'. But if the copy constructor for A is then called
afterwards, then things will crash again...

I also thought of setting a property in class A, like:

A special_function()
{
A my_A;
// do something with A.

// Prepare for special behaviour of the copy constructor.
A.in_special_function = true;

return A;
}

so that the copy constructor can test for that. But if NRVO is applied,
then the property remains set after A is returned and the special
behaviour of the copy constructor may be applied to the returned object
A somewhere in the code where I don't want it... For instance in the
situation:

void function2(A a)
{
}

function2(special_function());

Because the copy constructor is called when calling function2 while the
property 'A.in_special_function' may still be true at that time.

Any ideas maybe? Or is the description of my problem too vague :)

Jeroen
 

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

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top