2010-08-20 70 views
7

当你想从一个方法返回一个实例时,你是否创建了这个对象并且发回一个指针或者返回一个引用?这是什么正确的方法和方法签名?从函数返回指针或引用C++

+0

方法或函数。两者不同,答案可能不同。 – 2010-08-20 20:39:37

+0

@Martin - 怎么样?你是否将成员函数称为方法和非成员函数作为函数? – naivnomore 2010-08-20 20:45:42

+0

@naivnomore:是的(这是OO中的标准定义)。 – 2010-08-20 20:55:28

回答

8

在C++中有很多方法可以做到这一点。不幸的是,它们中的大多数导致混淆谁负责分配和释放对象。有两种方法,我推荐:

// Return a real object, automatic stack allocation. 
Foo GetFoo1() 
{ 
    Foo f; 
    // Init f. 
    return f; 
} 

// Use a smart, reference counted pointer that handles deallocation itself. 
boost::shared_ptr<Foo> GetFoo2() 
{ 
    boost::shared_ptr<Foo> f(new Foo); 
    // Init f 
    return f; 
} 
+0

我同意这条评论。应该注意的是,shared_ptr将其转换为TR1,并且在gcc和Visual Studio中都以std :: tr1 :: shared_ptr的形式实现。 unique_ptr应该注意,如果你有明确的“汇”和“来源”......但这在技术上是C++ 0x。如果你只使用C++ 98 ...你可以使用auto_ptr。但unique_ptr在各方面都优越。 – Dragontamer5788 2010-08-20 20:37:10

+0

对成员的引用如何(记住原始帖子是关于方法而不是函数)。 – 2010-08-20 20:38:00

+2

我不相信你可以返回对堆栈中分配的本地对象的引用。当你从GetFoo1返回时,f将超出范围 – crazyx 2010-08-20 20:54:00

4

如果我创建一个纯粹返回的实例,我会返回值作为第一首选项。

只有当对象类型实际上不可复制时,我才会考虑通过封装所有权转移的智能指针返回。

返回一个引用,我保留返回一个对象的引用,这个对象的所有权没有被传递出该函数,也就是说它已经被其他东西所拥有,并且它的存在被保证,直到函数返回后的一个定义的时间。

2

如果您指的是Factory Method之类的东西,通常您会返回一个指针。更好的是,返回一个智能指针,并且不会因使用原始指针而创建更多的泄漏。

例子:

std::auto_ptr<Gizmo> MyFactory::CreateGizmo() 
{ 
    return new Gizmo; 
} 
6

无论是价值回归(人错误地认为这是慢),或者,如果你返回一个多态型的覆盖,在C返回一个auto_ptr(或更好的unique_ptr ++ 0x中)。

你不使用shared_ptr的原因是你永远不能使你的指针离开它并使用不同的所有权语义。

永远不会返回对本地实例的引用。

+0

虽然有点过时了,但在这里有一个很好的Scott Meyers文章,这个答案在这里:http://www.aristeia.com/Papers/resourceReturnProblem.txt – SCFrench 2010-08-20 20:41:06

0

这实际上取决于控制实例生命周期的实例范围。如果这是一个本地实例,您可能会返回值,但会产生两次构建对象的代价(除非您使用RVO)。另一种选择是通过在函数内的堆中构造对象来返回指针。但是,使用这种方法,客户端将负责删除分配的内存,因此总是容易发生内存泄漏。这就是为什么你需要使用某种智能指针。 Anders Abel代码通过代码示例清楚地说明了上述两种方法。顺便说一句,你不能返回一个本地实例的引用,因为一旦函数结束,实例将超出范围。

6

答案取决于你在做什么以及谁负责释放。

第一种方法:在堆上分配并返回。曾经调用函数的人将负责删除返回的指针。

​​

然后,在一些其他的功能

void functionThatNeedsObject() 
{ 
    SomeObject* obj = constructObject(); 
    //You must delete obj when done 
} 

第二种方法:返回一个参考。您必须注意不要通过返回本地或临时变量超出范围。

不这样做:

int& DoubleValue(int nX) 
{ 
    int nValue = nX * 2; 
    return nValue; // return a reference to nValue here 
} // nValue goes out of scope here 

您可以返回作为参数传递给函数的变量或者变量的引用。

SomeStruct& RefFunction(SomeStruct& nX, SomeStruct& nY) 
{ 
    return nX; 
} //nX is still in scope because it was passed to us