在C ++中何时可以返回一个类实例?

时间:2016-11-25 00:09:23

标签: c++

我正在阅读Java to C++ crash course,除此之外,它还谈到了C ++中的内存管理。举例说明了必须做的事情:

Foo& FooFactory::createBadFoo(int a, int b)
{
    Foo aLocalFooInstance(a, b);  // creates a local instance of the class Foo
    return aLocalFooInstance;     // returns a reference to this instance
}

这不起作用,因为aLocalFooInstance会留下范围并被销毁。很好,对我来说很有意义。现在作为这个问题的一个解决方案,给出了以下代码:

Foo FooFactory::createFoo(int a, int b) 
{
    return Foo(a, b);  // returns an instance of Foo
}

我不明白:为什么第二个例子是有效的C ++代码?这两个例子中的基本问题是不一样的,即创建了Foo的实例,它会超出范围,因此当我们从方法返回时会被销毁?

4 个答案:

答案 0 :(得分:2)

说我们有代码

Foo FooFactory::createFoo(int a, int b) 
{
    return Foo(a, b);  // returns an instance of Foo
}

int main() {
    Foo foo = FooFactory::createFoo(0, 0);
}

区分创建的各种Foo对象非常重要。

从概念上讲,执行过程如下:

  1. 当评估return语句中的表达式Foo(a, b)时,会创建一个Foo类型的临时对象。
  2. 在评估了return语句中的表达式之后,将从该表达式初始化返回值本身。这导致创建另一个<{1}}类型的临时文件。
  3. 在步骤1中创建的临时文件已被销毁。
  4. 在步骤2中创建的临时值是调用函数中函数调用表达式Foo的结果。该临时用于初始化非临时对象FooFactory::createFoo(0, 0)
  5. 在步骤2中创建的临时文件已被销毁。
  6. 在存在复制省略和返回值优化的情况下,可以省略两个临时值。

    请注意,如果函数通过引用返回,则第2步创建新对象;它只创建一个引用。因此,在步骤3之后,所引用的对象不再存在,并且在步骤4中,初始化将从悬空引用发生。

答案 1 :(得分:1)

因为第二个示例按值返回对象,而不是通过引用返回。

第一个示例返回对对象实例的引用,第二个示例返回对象的实例。

您所展示的评论甚至明确说明了这一点。

在第一个示例中,仅返回引用,并且引用的对象将被销毁。

在第二个示例中,返回对象本身。这意味着对象“继续存在”,从某种程度上讲,它会在调用此函数的代码放置该对象的任何地方结束。

答案 2 :(得分:0)

当你返回一个实例时,你不会延长对象的生命周期,所以它会在函数的结束时被破坏,你的引用现在什么都没引用。

如果你返回一个类,那么该类被复制(除非RVO适用,这是一个完全不同的东西,效果相同)到外部该函数在被销毁之前,所以你现在拥有一个处于完美工作状态的创建对象的副本,并且可以正常使用。

答案 3 :(得分:0)

在第二个示例中,您(逻辑上)返回副本。想象一下,如果你返回一个int而不是Foo

int FooFactory::createInt(int a, int b) 
{
    return a+b;
}

你能看出这不是问题吗? 在C ++中,只要int可移动或可复制,Foo的工作原理与Foo相同。