在C++中初始化结构

28 c++ struct

作为这个问题的补充,这里发生了什么:

#include <string>
using namespace std;

struct A {
    string s;
};

int main() {
    A a = {0};
}
Run Code Online (Sandbox Code Playgroud)

显然,你不能将std :: string设置为零.有人可以提供一个解释(请参考C++标准,请参考)这里应该发生什么?然后解释一下):

int main() {
    A a = {42};
}
Run Code Online (Sandbox Code Playgroud)

这些都是明确界定的吗?

对我来说又一个令人尴尬的问题 - 我总是给我的结构构造者,所以这个问题从未出现过.

AnT*_*AnT 29

您的结构是一个聚合,因此聚合初始化的普通规则适用于它.该过程在8.5.1中描述.基本上整个8.5.1专用于它,所以我没有看到在这里复制整个事情的原因.一般的想法几乎与C中的一样,只适用于C++:你从右边拿一个初始化器,你从左边拿一个成员,然后用初始化器初始化成员.根据8.5/12,这应该是复制初始化.

当你这样做

A a = { 0 };
Run Code Online (Sandbox Code Playgroud)

你基本上复制初始化a.s0,即对于a.s它在语义上等同于

string s = 0;
Run Code Online (Sandbox Code Playgroud)

以上编译因为std::string可以从const char *指针转换.(并且它是未定义的行为,因为在这种情况下空指针不是有效参数.)

你的42版本不会因为同样的原因而编译

string s = 42;
Run Code Online (Sandbox Code Playgroud)

不会编译.42不是空指针常量,并且std::string无法从int类型转换.

PS以防万一:请注意,C++ 中聚合的定义不是递归的(例如,与POD的定义相反).std::string不是聚合,但它不会改变你的任何东西A.A仍然是一个聚合.


Mic*_*urr 8

8.5.1/12"聚合"说:

使用初始化程序列表中的初始化程序初始化聚合成员时,将考虑所有隐式类型转换(第4节).

所以

A a = {0};
Run Code Online (Sandbox Code Playgroud)

将使用NULL进行初始化char*(如AndreyTJohannes所示),以及

A a = {42};
Run Code Online (Sandbox Code Playgroud)

将在编译时失败,因为没有隐式转换将与std::string构造函数匹配.