是否从临时有效的 C++ 代码中获取引用?

Dav*_*óth 23 c++ reference temporary-objects c++17

我使用了以下语法糖:

for (auto& numberString: {"one", "two", "three", "four"}) { /* ... */}
Run Code Online (Sandbox Code Playgroud)

这是有效的代码吗?AFAIK,基于这个问题,这应该是非法的,但代码按预期运行。我认为我对此事的理解不正确。

据我所知,只有文字不应该有内存地址,但链接的问题正在讨论临时值和右值

Jod*_*cus 28

是的,该代码有效。

请记住(对于 C++17),编译器将在语义上用构造替换基于范围的 for 循环

{

    auto && __range = {"one", "two", "three", "four"};
    for (auto __begin = begin(__range), __end = end(__range); __begin != __end; ++__begin)
    {

        auto& numberString = *__begin;
        /* ... */
    }

}
Run Code Online (Sandbox Code Playgroud)

您会看到,替换中 的生命周期initializer_list延长到了最外层作用域内部的生命周期。__range

但请注意,如果范围表达式本身包含临时值,您仍然很容易导致未定义的行为:

struct some {
   auto get_list() { return {"one", "two", "three", "four"}; }
};

some foo() { return some{ }; }

for(auto& numberString : foo().get_list()) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

上面的代码将导致 <= C++20 中的悬空引用。仅在 C++23 中,由 创建的临时变量的生命周期foo()将得到延长,使其变得有效。另请参阅https://en.cppreference.com/w/cpp/language/range-for

  • 我很确定如果 `get_list` 返回对 `some` 成员的引用,您的第二个示例只会是未定义的。按原样,“foo”返回一个临时的“some”对象,该对象一直存在到完整表达式的末尾,该表达式的长度足以对其调用“get_list”。`get_list` 返回一个临时对象,然后根据通常的规则延长其生命周期。 (5认同)