从函数返回对象 [英] Returning object from function

查看:121
本文介绍了从函数返回对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在我真的很困惑如何和使用哪个方法来从函数返回对象。



场景A:
返回的对象存储在一个变量中,不需要修改。其寿命。因此,

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

调用为:

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





$ b b

Scneraio B:
返回的对象被存储在一个变量中,该变量在其生命周期中被修改。因此,

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

调用为:

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

我有一个问题:说Foo不能有一个默认的构造函数。那么你在这种情况下如何处理,因为我们不能这样写:

  Foo l_Foo 






方案C:

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

调用为:

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

我认为这不是推荐的因为它会招致额外的临时性。



你觉得怎么样?

解决方案

首先,让我们来看看在这里发生的事情: ://www.drdobbs.com/cpp/184403758rel =nofollow>本出版物作者:Andrei Anexandrescu。再次,它感觉奇怪但有用:

  class Foo {...} 

Foo GetFoo ){return Foo(); } //返回临时

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

这条规则说当引用被临时初始化时,扩展,直到引用超出范围。 (此回复引用标准)



(b)返回值优化 - ( wikipedia ) - 在情况下可以省略两个副本local - > return value - > local 。这是一个惊人的规则,因为它允许编译器更改可观察的行为,但有用。



有它。



p> 方案A:您正在返回一个临时项,并将其绑定到引用 - 临时项的生命周期延长到l_Foo的生命周期。



注意,如果 GetFoo 将返回引用而不是临时变量,则这将不起作用。



方案B:工作,除了它强制一个构造 - 构造 - 复制循环(这可能比单结构昂贵得多),以及您提到的需要一个默认构造函数的问题。



我不会使用该模式创建一个对象 - 只能改变现有对象。



strong>场景C:临时表的副本可以由编译器省略(从RVO规则)。不幸的是没有保证 - 但现代编译器确实实现了RVO。



C ++ 0x中的Rvalue引用允许Foo实现一个资源窃取构造函数,它不仅保证压缩副本,而且在其他情况下也很方便。



(我怀疑有一个编译器实现了右值引用而不是RVO,但是有些情况下RVO无法启动。)






这样的问题需要提到智能指针,例如 shared_ptr unique_ptr (后者是一个安全 auto_ptr )。他们也在 C ++ 0x 中。它们为创建对象的函数提供了一种备用模式。





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 ?

解决方案

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.


这篇关于从函数返回对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆