c++ - C ++:带有花括号初始化列表的函数调用表达式-标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
问题描述
考虑以下示例:
class X;
void f(const X &);
void g()
{
X x;
f({x});
}
在这种情况下,标准是否要求实现忽略花括号?不涉及任何优化。如果是,比从哪个版本开始?
乍一看,根据规则,应该有一个临时创建 - 当然,完全没有必要,但仍然如此。查看列表初始化我找不到任何相关的东西。X
这里不是聚合。
GCC 和 Clang 都-O0
生成了没有临时创建的代码——即使X
复制构造函数具有可观察到的副作用并且即使X
具有X(std::initializer_list<X>)
构造函数。
解决方案
in的X const &x
(的参数f
)的f({x})
初始化是复制初始化上下文中的列表初始化,由[dcl.init]/15
。因此,我们可以放弃这个函数,只问这意味着什么:
int main() {
X x;
X const &y = {x}; // still copy list initialization
}
现在,[dcl.init.list]
适用于 this 的第一个子句是[dcl.init.list]/3.9
,它表明您基本上只是放下大括号。
...如果初始化列表有一个类型的元素
E
并且T
[这里X const&
] 不是引用类型或其引用类型与引用相关E
,则从该元素初始化对象或引用(通过复制初始化复制-列表初始化,或通过直接初始化直接列表初始化);……
X const&
实际上是一个引用类型,但它的引用类型X const
确实和初始化器的类型有关X
,所以该子句仍然适用。现在我们只有
int main() {
X x;
X const &y = x; // (non-list/"plain") copy-initialization
}
当然这不会调用X
的构造函数(by [dcl.init.ref]/5.1
)。
请注意,上面的引用在您的 cppreference 页面上也略有改写:
...(如果
T
不是类类型),如果花括号初始化列表只有一个元素并且T
不是引用类型,或者是引用类型与该类型的基类相同或者是该类型的基类的引用类型元素的,T
是直接初始化(在直接列表初始化中)或复制初始化(在复制列表初始化中),...。
也许“T
不是引用类型”或“T
不是类类型”使这在雷达下飞行,但这是您正在寻找的子句,因为a)引用类型确实不是类类型,b)先决条件中的“或...”使其适用。从缺少版本控制框来看,这种行为与列表初始化本身一样古老:从 C++11 开始。
推荐阅读
- python - 使用 Python 从我的网站上传到我的 CDN
- c - 测试 GNU 扩展
- python - 二元分类之间图像格式/质量的差异会影响卷积神经网络的训练吗?
- javascript - 有没有办法获取自动幻灯片 w3 轮播的当前幻灯片编号?
- c# - ASP.NET 5 - TypeLoadException - 无法从程序集“Microsoft.JSInterop.WebAssembly”加载类型“WebAssembly.JSInterop.JSCallInfo”
- ruby-on-rails - Rails 控制器看起来正在保存所有参数,但是当我拉记录时缺少字段 - 像 post 函数
- syntax - IF BRANCH 和 AND 作为 OPERATOR 有什么不同?
- java - 如何在 java 中使用 ModelAndView 操作 http 响应?
- sql - 从表 2 中提取最后一个日期时间,该日期时间在日期时间被拉入表 1 之前发生
- html - 如何在 Flask-WTforms StringField 中隐藏活动字符计数器并实现 CSS