是否允许打印悬空引用的地址?

for*_*818 8 c++ reference undefined-behavior language-lawyer

考虑这段代码,它是从这里稍微修改的:

#include <iostream>

void foo() {
    int i;
    static auto f = [&i]() { std::cout << &i << "\n";};
    f();
}

int main() {
    foo();
    foo();
}
Run Code Online (Sandbox Code Playgroud)

lambdaf仅在第一次调用时初始化,在第二次调用期间捕获的变量不再存在,lambda 保留悬空引用,但仅打印其地址。gcc没有明显问题,输出看起来没问题:

0x7ffc25301ddc
0x7ffc25301ddc
Run Code Online (Sandbox Code Playgroud)

获取悬空引用的地址是未定义的行为,还是可以?

对于一个非常相似的示例,gcc ( -Wall -Werror -pedantic -O3) 会生成警告:

#include <iostream>

auto bar() {
    int i;
    return [&i]() {std::cout << &i << "\n"; };
}

int main() {
    bar()();
}
Run Code Online (Sandbox Code Playgroud)

警告:

source>:5:14: error: address of stack memory associated with local variable 'i' returned [-Werror,-Wreturn-stack-address]
    return [&i]() {std::cout << &i << "\n"; };
             ^
<source>:5:14: note: captured by reference here
    return [&i]() {std::cout << &i << "\n"; };
Run Code Online (Sandbox Code Playgroud)

当然,gcc 编译第一个示例并生成预期的(?)输出,同时警告第二个示例这一事实并不意味着什么。在标准中的哪里可以找到使用悬空引用的地址是否可以?

PS:我想答案就在[basic.life]中的某个地方,尽管我浏览了几次,但我很难看出什么适用以及它试图告诉我什么。

Rem*_*eau 0

是的,这是未定义的行为,因为将&地址运算符应用于引用会检索所引用对象的地址,在您的示例中,该地址不再存在,因为它已超出范围并被销毁。您无法获取不存在的对象的地址。

  • _不,他们没有。一旦对象超出范围并被销毁,它就不再存在。_我在您的评论中没有看到对标准的引用。(而且,顺便说一句,对象没有范围。) (2认同)