2016-11-25 27 views
1

我正在阅读Java to C++ crash course,除此之外,它讨论了C++中的内存管理。通过一个实例来展示一下一定不能做的:在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的实例,它将超出范围,因此在从方法返回时会被销毁?

+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. 当在返回语句中的表达式Foo(a, b)被评估,创建Foo类型的临时对象。
  2. 在评估了return语句中的表达式之后,返回值本身将从该表达式初始化。这导致的另一个创建类型Foo的临时。
  3. 在步骤1中创建的临时文件被销毁。
  4. 在步骤2中创建的临时函数是调用函数中函数调用表达式FooFactory::createFoo(0, 0)的结果。该临时用于初始化非临时对象foo
  5. 在步骤2中创建的临时文件被销毁。

在存在复制elision和返回值优化的情况下,两个临时对象都可能被忽略。

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

1

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

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

您显示的评论甚至明确指出。

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

在第二个示例中,返回对象本身。这意味着对象“继续存在”,以某种方式说话,并且在调用该函数的代码放置该对象的任何地方都会结束。

0

当你返回一个实例时,你不会延长对象的生命周期,所以它会在函数的结束大括号中被销毁,而你的引用现在不引用任何东西。

如果返回一个类,则该类被复制(除非RVO适用,这是一个有效运作同样是完全不同的东西)之外面前的功能被破坏到,所以你现在有一个副本创建完美的工作顺序并可以很好地使用的对象。

0

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

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

你可以看到,这不会是一个问题? 在C++中,只要Foo是可移动或可复制的,Foo将以与int相同的原因工作。

相关问题