初始化——括号的类型如何影响C++中的对象生存期?

yfwxisqw  于 2021-09-08  发布在  Java
关注(0)|答案(1)|浏览(361)

我的一个朋友给我看了一个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情况下延长。
你能解释一下为什么大括号的类型会影响物体的寿命吗?

watbbzwu

watbbzwu1#

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开始)

相关问题