大括号的类型如何影响C++中的对象生命周期?

我的一个朋友给我看了一个 C++20 程序:

#include <iostream>

struct A
{
    A() {std::cout << "A()n";}
    ~A() {std::cout << "~A()n";}
};

struct B
{
    const A &a;
};

int main()
{
    B x({});
    std::cout << "---n";
    B y{{}};
    std::cout << "---n";
    B z{A{}};
    std::cout << "---n";
}

在 GCC 中,它打印:

A()
~A()
---
A()
---
A()
---
~A()
~A()

https://gcc.godbolt.org/z/ce3M3dPeo

因此,A在 y 和 z 情况下,的寿命会延长。

在 Visual Studio 中,结果是不同的:

A()
~A()
---
A()
---
A()
~A()
---
~A()

所以A只有在 y 的情况下,的寿命才会延长。

你能解释一下为什么大括号的类型会影响对象的生命周期吗?

回答

gcc 是正确的。只有在聚合初始化中使用列表初始化语法(即使用大括号)时,临时对象的生命周期才会延长。

(C++20 起)使用直接初始化语法(括号)而不是列表初始化语法(大括号)初始化的聚合的引用元素中的引用的临时绑定一直存在,直到包含初始化器的完整表达式结束.

struct A {
  int&& r;
};
A a1{7}; // OK, lifetime is extended
A a2(7); // well-formed, but dangling reference

对于直接初始化:

(强调我的)

否则,如果目标类型是(可能是 cv 限定的)聚合类,则按照聚合初始化中的描述对其进行初始化,除了允许缩小转换、不允许指定的初始值设定项、指向引用的临时绑定不会延长其生命周期,没有大括号省略,任何没有初始化器的元素都是值初始化的。(C++20 起)

  • IIRC 的意图(在 `()` 后面不延长生命周期)是模仿用户提供的构造函数的行为,它不能延长生命周期,因为它们间接地(从引用参数)初始化引用成员,而生命周期扩展不会用另一个引用初始化一个引用时传播。

以上是大括号的类型如何影响C++中的对象生命周期?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>