Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
124 views
in Technique[技术] by (71.8m points)

c++ - Returning object from function

I am really confused now on how and which method to use to return object from a function. I want some feedback on the solutions for the given requirements.

Scenario A: The returned object is to be stored in a variable which need not be modified during its lifetime. Thus,

const Foo SomeClass::GetFoo() {
 return Foo(); 
}

invoked as:

someMethod() {
 const Foo& l_Foo = someClassPInstance->GetFoo();
//...
}

Scneraio B: The returned object is to be stored in a variable which will be modified during its lifetime. Thus,

void SomeClass::GetFoo(Foo& a_Foo_ref) {
     a_Foo_ref = Foo(); 
    }

invoked as:

someMethod() {
 Foo l_Foo;
 someClassPInstance->GetFoo(l_Foo);
//...
}

I have one question here: Lets say that Foo cannot have a default constructor. Then how would you deal with that in this situation, since we cant write this anymore:

Foo l_Foo

Scenario C:

Foo SomeClass::GetFoo() {
 return Foo(); 
}

invoked as:

someMethod() {
 Foo l_Foo = someClassPInstance->GetFoo();
//...
}

I think this is not the recommended approach since it would incur constructing extra temporaries.

What do you think ? Also, do you recommend a better way to handle this instead ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First, let's look into the things that come into play here:

(a) Extending lifetime of a temporary when it's used to initialize a reference - I learnt about it in this publication by Andrei Anexandrescu. Again, it feels weird but useful:

class Foo { ... }

Foo GetFoo() { return Foo(); }  // returning temporary

void UseGetFoo()
{
   Foo const & foo = GetFoo();
   // ... rock'n'roll ...
   foo.StillHere();
}

The rule says that when a reference is initialized with a temporary, the temporary's lifetime is extended until the reference goes out of scope. (this reply quotes the canon)

(b) Return Value Optimization - (wikipedia) - the two copies local --> return value --> local may be omitted under circumstances. That's a surprising rule, as it allows the compiler to change the observable behavior, but useful.

There you have it. C++ - weird but useful.


So looking at your scenarios

Scenario A: you are returning a temporary, and bind it to a reference - the temporary's lifetime is extended to the lifetime of l_Foo.

Note that this wouldn't work if GetFoo would return a reference rather than a temporary.

Scenario B: Works, except that it forces a Construct-Construct-Copy-Cycle (which may be much more expensive than single construct), and the problem you mention about requiring a default constructor.

I wouldn't use that pattern to create a object - only to mutate an existing one.

Scenario C: The copies of temporaries can be omitted by the compiler (as of RVO rule). There is unfortunately no guarantee - but modern compilers do implement RVO.

Rvalue references in C++ 0x allows Foo to implement a resource pilfering constructor that not only guarantees supression of the copies, but comes in handy in other scenarios as well.

(I doubt that there's a compiler that implements rvalue references but not RVO. However there are scenarios where RVO can't kick in.)


A question like this requires mentioning smart pointers, such as shared_ptr and unique_ptr (the latter being a "safe" auto_ptr). They are also in C++ 0x. They provide an alternate pattern for functions creating objects.



与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...