首页 > 解决方案 > 聚合初始化中 mem-initializer 的有效性和/或生命周期延长

问题描述

CWG 1815询问(稍作修改):

struct A {};
struct B { A&& a = A{}; };
B b1;         // #1
B b2{A{}};    // #2
B b3{};       // #3

[...]#2是聚合初始化,它绑定B::a到初始化器中的临时变量 for b2,从而将其生命周期延长到b2. #3是聚合初始化,但不清楚非静态数据成员初始化器中的临时生命周期是否B::a应该#2#1.

根据关于该问题的注释,在 Issaquah (2014-02) CWG 打算使#3行为类似于#2;也就是说,格式正确,并且执行b3.a绑定的临时对象的生命周期延长。但在下一次 ISO 会议(Rapperswil,2014-06)上,通过了CWG 1696的决议,表面上解决了 CWG 1815,但采用的语言似乎使格式#3不正确

11 - 从默认成员初始化程序绑定到引用成员的临时表达式格式不正确。

但是,该条款下的示例不考虑聚合初始化(如 CWG 1815 中),而仅考虑构造函数的初始化;具体来说,定义为默认的默认构造函数:

struct A {
  A() = default;        // OK
  A(int v) : v(v) { }   // OK
  const int& v = 42;    // OK
};
A a1;                   // error: ill-formed binding of temporary to reference
A a2(1);                // OK, unfortunately

因此,虽然措辞看起来很明确,但也似乎与委员会的意图相反,这可能是认为措辞有缺陷的理由。

在实现实践方面,我们可以看到存在相当大的差异:

海合会 MSVC 国际商会
#1 ❌销毁 ✅拒绝 ☠️ 泄漏 ❌销毁
#2 ✅ 延长 ✅ 延长 ✅ 延长 ✅ 延长
#3 ❌ 延长 ❌ 延长 ❌ 延长 ❌销毁

(这里,“销毁”是指临时在声明结束时被销毁,即不延长生命周期。✅ 表示符合,❌ 不符合,☠️ 明显缺陷。)但是,除了 ICC,编译器同意延长生命周期在#3,与当前的措辞相反。奇怪的是,尽管执行了生命周期延长,但 Clang警告说它无法这样做,这表明开发人员认为在这种情况下标准要求延长生命周期:

警告:抱歉,不支持使用默认成员初始化程序聚合初始化创建的临时的生命周期延长;临时的生命周期将在完整表达式结束时结束 [-Wdangling]

问题

鉴于 CWG 的明确意图和实施差异,是否合理认为当前措辞有缺陷并依赖#3于 委员会是否意识到这种差异,是否有可能在近期或中期解决它(例如,作为 C++20 的 DR)?

标签: c++c++14language-lawyerlifetimetemporary-objects

解决方案


推荐阅读