c ++返回局部变量的const引用

时间:2010-01-13 15:21:17

标签: c++ reference const inline

是否可以/ ok返回一个const引用,即使函数返回的值是该函数的局部变量?我知道一旦函数返回,本地函数就不再有效 - 但如果函数是内联的并且返回的值仅在调用者范围内使用,该怎么办?那么函数的本地应该包含在调用者堆栈框中,不是吗?

7 个答案:

答案 0 :(得分:8)

不要指望它。即使这适用于1个编译器,它也不是标准支持的行为,并且可能会破坏其他行为。

答案 1 :(得分:6)

不,不行。局部变量在堆栈上声明,并且堆栈在方法调用之间不断变化。此外,超出范围的对象也会被破坏。始终返回本地变量的副本。

考虑以下代码:

#include <iostream>
using namespace std;

class MyClass
{
public:
  MyClass() { cout << "ctor" << endl; }
  ~MyClass() { cout << "dtor" << endl; }
  MyClass(const MyClass& r) { cout << "copy" << endl; }
};

const MyClass& Test()
{
  MyClass m;
  return m;
}

int main()
{
  cout << "before Test" << endl;
  MyClass m = Test();
  cout << "after Test" << endl;
}

这将打印出来:

before Test
ctor
dtor
copy
after Test
dtor

您尝试复制的对象已调用其析构函数,可能处于无效状态。

答案 2 :(得分:4)

inline 是保证 - 这是建议。即使您使用技巧强制内联,您也永远无法确定结果,特别是如果您想要保持便携性。

因此,这样做。

答案 3 :(得分:1)

这样做会调用未定义的行为。

  • 没有办法强制编译器内联函数。 inline只是一个建议 - __forceinline
  • 也是如此
  • 即使您可以保证函数将被内联,仍然会执行相关变量的析构函数,并为您提供对死对象的引用。
  • 最重要的一个 - C ++的堆栈概念是由范围界定的 - 而不是按功能划分。

#include <iostream>
int main()
{
  {
    int a = 5;
    std::cout << std::hex << "0x" << &a << std::endl;
  }
  {
    int b = 10;
    std::cout << std::hex << "0x" << &b << std::endl;
  }
}

我的编译器将'a'和'b'放在不同的内存地址上。 除非我开启优化。您可能会认为重新使用您的对象之前占用的内存是一种优化。

你在这里试图解决一个特殊问题吗?如果您担心这一点,还有其他方法可以减少创建的临时对象的数量。

答案 4 :(得分:1)

正如其他人所说,这是危险的。如果您的编译器支持NRVO(命名返回值优化),并且您的函数使用并返回您希望通过ref以相当简单的方式返回的局部变量,那么它也是不必要的。

NRVO允许编译器在某些条件下避免复制构造 - 通常是避免按值返回对象的主要原因。 VC ++ 8支持这一点(以前版本中的delta),它在常用代码中提供了相当多的perf diff。

答案 5 :(得分:0)

当被叫者超出范围时,该值超出范围。所以不,它消失了。

但是如果你想要一个相当难看的解决方案(并且红旗警告你你的设计可能需要重构),你可以这样做:

const MyObj& GetObj()
{
  static const MyObj obj_;
  return obj_;
}

...但是这个解决方案如果充满危险,特别是如果对象是可修改的,或者在多线程环境中做了一些非常重要的事情。

答案 6 :(得分:0)

inline关键字不保证该函数真正内联。不要这样做。

相关问题