c++ - 聚合初始化中 mem-initializer 的有效性和/或生命周期延长
问题描述
CWG 1815询问(稍作修改):
struct A {}; struct B { A&& a = A{}; }; B b1; // #1 B b2{A{}}; // #2 B b3{}; // #3
[...]
#2
是聚合初始化,它绑定B::a
到初始化器中的临时变量 forb2
,从而将其生命周期延长到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)?
解决方案
推荐阅读
- postgresql - 如何访问postgresql中的特定数据库
- python - 在 python 中使用 WSL bash
- puppet - 木偶板上未更新的事实
- javascript - 从 Google Analytics 向网页添加查看次数
- c++ - 有时如何以及为什么使用未编译的 C/C++?
- c# - 在 Google.Apis.Pagespeedonline.v5 中,如何一次调用所有类别?
- influxdb - 从 Influxdb 子查询插入,缺少行且时间设置为 0
- javascript - 设置反应 CreatableSelect 的最大字符输入大小
- python-3.x - 如何为 pandas 表着色并将其导出为 html
- javascript - Gulp:任务从未定义:任务