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

发布于 2024-08-17 21:25:33 字数 123 浏览 4 评论 0原文

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

is it possible/ok to return a const reference even if the value the function returns is a local variable of this function? i know that locals are not valid anymore once the function returns - but what if the function is inlined and the returned value is only used within the callers scope? then the locals of the function should be included in the callers stackframe, no?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

攒一口袋星星 2024-08-24 21:25:33

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

Don't count on it. Even if this works on 1 compiler, it's not standard supported behavior and is likely to break on others.

隔岸观火 2024-08-24 21:25:33

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

考虑以下代码:

#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

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

No, it's not OK. Local variables are declared on the stack, and the stack keeps changing between method calls. Also, the objects that get out of scope get destroyed. Always return a copy of a local variable.

Consider this code:

#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;
}

This will print out:

before Test
ctor
dtor
copy
after Test
dtor

The object you're trying to copy has already called its destructor and may be in an invalid state.

一梦等七年七年为一梦 2024-08-24 21:25:33

内联不是保证——它是建议。即使您使用技巧来强制内联,您也永远无法确定结果,特别是如果您想保持可移植性。

因此,不要这样做。

inline is not a guarantee -- it's a suggestion. Even if you use tricks to force inline, you'll never be sure about the result, especially if you want to remain portable.

Hence, don't do it.

等风也等你 2024-08-24 21:25:33

这样做会引发未定义的行为。

  • 无法强制编译器内联该函数。 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”放在不同的内存地址处。 除非我打开优化。您很可能认为这是一种重用对象先前占用的内存的优化。

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

Doing that invokes undefined behaviour.

  • There's no way of forcing a compiler to inline the function. inline is just a suggestion - so is __forceinline
  • Even if you could guarantee that the function would be inlined, the destructor for the variable in question will still be executed, leaving you with a reference to a dead object.
  • And the big one - C++'s concept of the stack is delimited by scope - not by function.

#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;
  }
}

My compiler puts 'a' and 'b' at different memory address. Except when I turn optimizations on. Yours may well decide that it's an optimization to reuse the memory your object previously occupied.

Is there a paticular problem you're trying to solve here? There are other ways of reducing the number of temporary objects created if that's your concern.

南街九尾狐 2024-08-24 21:25:33

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

NRVO 允许编译器在某些条件下避免复制构造 - 通常是避免按值返回对象的主要原因。 VC++ 8 支持这一点(之前版本的增量),并且它在常用代码中产生了相当多的性能差异。

As others have noted, this is dangerous. It's also unnecessary, if your compiler supports the NRVO (Named Return Value Optimization), and your function uses and returns the local variable you would have liked to return by ref in a fairly simple way.

The NRVO allows the compiler to avoid copy construction under certain conditions - typically the main reason to avoid returning objects by value. VC++ 8 supports this (a delta on previous revisions) and it makes quite a bit of perf diff in frequently used code.

撩起发的微风 2024-08-24 21:25:33

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

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

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

......但是这个解决方案如果充满危险,特别是如果对象是可修改的,或者在多线程环境中有些不平凡的事情。

The value falls out of scope when the callee falls out of scope. So no, it is gone.

But if you want a fairly ugly solution (and a red flag warning you that your design might need refactoring), you can do something like this:

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

...but this solution if fraught with peril, especially if the object is modifyable, or does something non-trivial in a multithreaded environment.

错爱 2024-08-24 21:25:33

inline 关键字并不能保证该函数确实是内联的。不要这样做。

The inline keyword doesn't guarantee that the function is really inlined. Don't do it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文