2012-08-30 62 views
4

我一直在阅读迈尔斯书,并通过参考/指针与价值观返回了该项目。 的一点是,如果我们的例如功能是这样的:C++:通过引用返回值返回

ClassA& AddSomething(ClassA classA) 
{ 
    ClassA tempClassA; 
    //... do something on tempClassA 
    return tempClassA; 
} 

这是行不通的,因为我们返回到被栈上创建一个对象的引用,现在是死的,该函数完成。

他给出了两个解决方案:

  1. 使用函数内的局部静态ClassA的。这有其 的问题,但至少我们可以确定该对象存在。
  2. 作为对象返回:

    ClassA AddSomething(ClassA classA) 
    { 
        ClassA tempClassA; 
        //... do something on tempClassA 
        return tempClassA; 
    } 
    

现在,如果我做的事:

ClassA obj1; 
ClassA obj2 = AddSomething(obj1); 

我的困惑,现在,在执行这条线时:

  1. tempClassA的“副本”被制作并传递给C的拷贝构造函数 lassA(初始化obj2)? OR
  2. tempClassA被传递给ClassA的拷贝构造函数 ,因为拷贝构造函数需要引用。

所以基本上,传递给拷贝构造函数的是tempClassA(它是在函数内部的堆栈中创建的)的引用,或者是对tempClassA副本的引用。

此外,我的另一个问题是,我读过,如果我得到一个函数局部变量的引用,在这种情况下,本地变量将不会被删除。 例如,

ClassA & classRef = AddSomething(obj1); 

在这种情况下,如果AddSomething()返回一个引用,则classRef不是指向一个已删除的参考,因为局部变量将被保留。我对此有正确的理解吗?

+0

看看[copy elision](http://en.wikipedia.org/wiki/Copy_elision)。 – juanchopanza

回答

2

当按值返回对象时,会发生两个副本:一个从局部变量返回到返回值,另一个从返回值到目标对象。但是,允许执行elide这些副本中的一个或两个;第一种情况称为return value optimisation(RVO),第二种称为copy elision

Object some_function() { 
    return Object(); // copy Object() into return value; candidate for RVO 
} 
Object another_function() { 
    Object obj; 
    return obj;   // copy obj into return value; candidate for NRVO 
} 
Object result = some_function(); // copy return value into result; candidate for copy elision 

上述第二个函数为细化类型RVO的候选称为命名返回值优化;最简单的RVO形式仅适用于构造返回值的返回语句。

关于你的第二个问题,终生延长只适用于const对值返回的对象的引用;第二个问题中的代码不会延长任何对象的生命周期。有关更多详细信息,请参见Returning temporary object and binding to const reference

5

最糟糕的是,您是对的:将tempClassA的副本传递给拷贝构造函数。但编译器允许删除该副本并以tempClassA的格式构造结果。这就是所谓的“退货价值优化”,即RVO。我不知道一个不这样做的编译器。

0

您永远不能通过引用返回函数局部变量。

const ClassA& classRef = AddSomething(obj1); 

因为如果AddSomething返回由局部参考对象,这将是由一个悬挂引用不存在的对象:即使你使用const引用捕捉返回值这样它不会工作时间classRef可以引用它。