正在初始化不可复制且不可移动类型的成员



给定一个不可复制/可移动的结构体U,该结构体的membes不能在构造函数中赋值(请参见C(。它们只能通过成员初始值设定项列表进行初始化(请参见S(。

struct U {
U(int x);
U(U &other) = delete;
U(U &&other) = delete;
};
struct S {
S(int x) : u(x) {}
U u;
};
struct C {
C(int x) { u = U(x); }  // compiler complains: cannot assign
U u;
};

错误:

<source>:13:5: error: constructor for 'C' must explicitly initialize the member 'u' which does not have a default constructor
C(int x) { u = U(x); }
^
<source>:14:7: note: member is declared here
U u;
^
<source>:1:8: note: 'U' declared here
struct U {
^
<source>:13:18: error: object of type 'U' cannot be assigned because its copy assignment operator is implicitly deleted
C(int x) { u = U(x); }
^
<source>:4:5: note: copy assignment operator is implicitly deleted because 'U' has a user-declared move constructor
U(U &&other) = delete;
^

代码在这里:https://godbolt.org/z/11nvh1ze4

编译器当然理所当然地抱怨。如果在构造函数体中计算x,则无法使用初始值设定项列表。有什么语法可以允许这样做吗?

不能在构造函数体中初始化它。在执行构造函数的主体之前对成员进行初始化。如果x是在调用构造函数时计算的,那么您仍然可以使用成员初始值设定项列表。例如,当您有一个void f(int&)需要调用以检索u:的参数时

struct C {
C(int x) : u(compute_x(x)) { } 
U u;
private:
static int compute_x(int x) { f(x); return x; }
};

还有另一个现已删除的答案,它提出了一个关于构造函数心理模型的好观点。这里需要说明的是,构造函数主体不用于初始化成员。这种情况发生在身体运动之前。一旦掌握了窍门,你会发现自己编写了许多构造函数,它们的主体只不过是{},因为构造函数除了设置类成员之外,实际上并不常见。

最新更新