5

我知道的

我知道返回临时对象的 const 引用是可以的!(像这个例子:)

class A {
public:
  virtual const A& clone () { return (A()); }
  virtual std::string name() const { return ("A"); }
};

返回临时对象并绑定到 const 引用

但!

如果我想这样做,它仍然是正确的:

class B : public A {
public:
  virtual const A& clone () { return (B()); }
  virtual std::string name() const { return ("B"); }
};

我认为是的,但在执行时,返回的对象仍被视为 A 对象(如本例中所示:)

主文件

#include <iostream>
#include <string>
int main() {
  B bb;
  A* aa = &bb;

  std::cout << aa->clone().name() << std::endl;
}

输出

valgrind ./a.out
==14106== Use of uninitialised value of size 8
==14106==    at 0x401BF9: main (main.cpp:8)
==14106==  Uninitialised value was created by a stack allocation
==14106==    at 0x401BF2: main (main.cpp:8)
B

这是一个 B.. 是的.. 但是这个警告是相当可怕的....

编辑

谢谢你,我知道我的错误......但我想知道其他一些事情......

执行此操作时,堆栈中到底发生了什么?

4

1 回答 1

11

绑定对临时对象的引用会延长临时对象的生命周期……除非没有。§12.2 [class.temporary]/p5,重点补充:

引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,但以下情况除外:

  • 临时绑定到构造函数的ctor-initializer (12.6.2) 中的引用成员将持续存在,直到构造函数退出。
  • 临时绑定到函数调用 (5.2.2) 中的引用参数将持续存在,直到 包含调用的完整表达式完成。
  • 临时绑定到函数返回语句 (6.6.3) 中的返回值的生命周期不会延长;临时在 return 语句中的完整表达式的末尾被销毁。
  • 临时绑定到new-initializer (5.3.4) 中的引用,直到包含 new-initializer的完整表达式完成为止。

您链接的问题中的案例(std::string foo(); const std::string & s = foo();)是可以的;的临时返回的生命周期foo()被延长,直到s生命周期结束。在您的代码中,临时值绑定到返回值,并且根据上面的第三个要点,它的生命周期没有延长,并且您的函数返回一个悬空引用。

通常来说,clone()函数应该返回一个指向堆分配副本的指针。

于 2014-10-09T16:33:21.147 回答