c++ - S() 与 S{} 之间的区别?
问题描述
在下面的代码中,两个赋值有什么区别?在这两种情况下, value.v 是否会被默认构造,而 x 会被初始化为 42?
struct S
{
std::vector<int> v;
int x = 42;
};
S value;
void foo()
{
value = S();
value = { };
}
解决方案
S()
并且S{}
在几乎所有情况下都意味着同样的事情。但并非所有情况。
- 如果
S
不是类类型,同样的事情:值初始化。 If
S
是一个非聚合的类类型,仍然主要意味着相同的事情:值初始化。除了以下情况:struct X { X(std::initializer_list<int>); }; auto x1 = X(); // ill-formed auto x2 = X{}; // ok, calls constructor
if
S
是一个聚合,thenS()
是值初始化,但是S{}
是聚合初始化。即使这在很多时候也意味着同样的事情。但并非所有时候。
示例 1:显式默认构造函数使聚合初始化格式错误
struct A { explicit A(int = 0); };
struct B { A a; };
B b; // OK
B b2 = B(); // OK
B b3{}; // error through trying to copy-list-initialize a = {}
示例 2:某些上下文中的值初始化首先进行零初始化
struct C { C() {} int i; };
struct D { C a; };
D d1{}; // d1.a.i is indeterminate
D d2 = D(); // d2.a.i is zero
但是,在 OP 示例中,whileS
是具有隐式定义的默认构造函数的聚合 - 这是一个有趣的案例。但是在这里,额外的零初始化没有改变语义,我们正在初始化x
并42
默认构造v
任何一种方式。
请注意,在 OP 中,这也会调用(并打算调用)移动赋值运算符S{}
:
value = { };
这也有可能完全调用不同的运算符,因为{}
最终可能会在不同的赋值运算符重载中将“更好”绑定到某些不同的参数。std::optional
必须跳过一些钩子以确保opt = {}
实际调用移动赋值运算符。
推荐阅读
- bash - `bash` 正在泄漏内存,我在哪里报告它?
- reactjs - 在 useEffect 挂钩中使用对象属性而不是对象作为依赖项是不好的做法吗?
- bootstrap-5 - Bootstrap 5:如何添加 $font-family-serif 变量
- typescript - 带有 Expo 和 Typescript 的 NPM 工作区
- android - 代码已粘贴,但它在 Android SSH 客户端上执行了相反的行顺序
- vba - VBA 用户表单组合框是 Outlook 联系人姓名列表和命令按钮,用于在选择姓名时搜索匹配的联系人家庭电话号码
- javascript - 以闪亮的方式删除html表中的特定行
- python - 如何使用用户输入迭代地构建 pd 系列,一次一个单元格?
- flutter - 从 Flutter 中的异步方法中调用一个确定的值。等待问题
- mysql - .ibd 文件在 ubuntu 服务器上占用太多空间