返回对本地int变量的引用是否总是未定义行为?

5
我了解到我们不应该返回指向本地变量的指针或引用。在下面给出的例子中,当我在函数foo内写入return i;时,我理解我正在返回对本地变量的引用。在函数外使用该引用将导致未定义的行为。
#include <iostream>

const int& foo()
{
    int i = 5;
    return i;//returning reference to a local variable
}

const int& func()
{
    return 5;
}

int main()
{
    const int& ref = func();
    const int& f = foo();
    std::cout<<f<<std::endl; //I know this is undefined behavior because we're using a reference that points to a local variable 
    std::cout<<ref; //But IS THIS UNDEFINED BEHAVIOR too?
}

我的问题是,对于函数 func 内的返回语句 return 5; 是否同样适用。我知道在 C++17 中有强制复制省略。所以我的问题针对所有现代 C++ 版本(C++11、C++17 等)。这种行为是否取决于 C++ 版本。

特别地,我知道语句 std::cout<<f<<std::endl;main 函数中总是未定义的行为,因为我们正在使用指向局部变量的引用(悬垂引用)。但是语句 std::cout<<ref; 是否也会导致未定义的行为?如果不是,为什么?这里会发生什么。

PS:我可能描述第一个 cout 语句的实际情况是错误的。如果我错了,请纠正我。


@463035818_is_not_a_number 你说:“返回对局部变量的引用总是UB”。返回对局部变量的引用总是UB,还是实际上使用该返回值才构成UB? - Jason
我相信返回值优化仅适用于实际上通过值返回的返回语句,因此它不适用于函数返回const int&而不是首先返回int的情况。我不确定临时生命周期延长是否适用于这两种情况,因为您绑定到了一个const引用。 - Nathan Pierson
Clang 给出了针对你的 func 的警告:*warning : returning reference to local temporary object [-Wreturn-stack-address]*。输出结果是垃圾。 - Adrian Mole
在早期的FORTRAN实现中,一些文字常量被存储在普通内存中。因此,您可以编写FORTRAN等效的 func() = 6; std::cout << 5 << '\n';,程序将显示值6,因为对func()的赋值更改了文字5的值。 - Pete Becker
1个回答

2

返回对局部 int 变量的引用是否总是未定义行为?

从技术上讲,不是。返回对局部变量(无论类型如何)的引用本身从来都不是未定义行为。但如果变量是非静态的,则这样返回的引用将始终无效,并且通过无效引用间接引用始终是未定义行为。

const int& func()
{
    return 5;
}

int main()
{
    const int& ref = func();
    std::cout<<ref; //But IS THIS UNDEFINED BEHAVIOR too?
}
是的。您通过无效的引用进行了间接操作,这种行为是未定义的。

func() 本身可能没问题,但是初始化一个引用 const int& ref 可能会导致未定义的行为,因为引用必须用 有效对象 进行初始化,而在 func 中的临时变量已经被销毁并且其存储空间已经消失。如果你有 const int* ptr = &func(); 的话,这看起来不像是个问题。这可能类似于 int arr[5]; int& past_the_end = arr[5]; 是非法的,但 int* past_the_end = &arr[5]; 不是。 - Artyer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接