大括号的类型如何影响 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 是正确的。只有在聚合初始化中使用列表初始化语法(即使用大括号)时,临时对象的生命周期才会是 extended

(C++20 起)一个临时绑定到一个引用元素中的引用 使用直接初始化语法(括号)初始化的聚合 与列表初始化语法(大括号)相反,直到结束 包含初始值设定项的完整表达式。

table-of-contents

对于direct initialization

(强调我的)

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