lho*_*hog 1 c++ class move-constructor
我有一段这样的现有代码:
struct Base {
Base() = default;
};
struct Derive: public Base
{
Derive() = default;
Derive(const Derive&) = delete;
Derive(Derive&& p) { *this = std::move(p); }
Derive& operator = (const Derive& p) = delete;
Derive& operator = (Derive&& p) {
return *this;
}
};
int main() {
Derive p;
}
Run Code Online (Sandbox Code Playgroud)
它编译并运行。现在我想稍微更改类定义,以便 Base 或 Derived 类始终使用某些整数参数构造,并且永远不会在没有此类参数的情况下构造。
因此,如果我尝试以下更改:
struct Base {
Base() = delete;
Base(int a_) : a{a_} {};
private:
int a; //new mandatory param;
};
struct Derive: public Base
{
Derive() = delete;
Derive(int a_) : Base(a_) {};
Derive(const Derive&) = delete;
Derive(Derive&& p) { *this = std::move(p); }
Derive& operator = (const Derive& p) = delete;
Derive& operator = (Derive&& p) {
return *this;
}
};
int main() {
Derive p{1};
}
Run Code Online (Sandbox Code Playgroud)
我收到编译错误
main.cpp:15:2: error: call to deleted constructor of 'Base'
Derive(Derive&& p) { *this = std::move(p); }
^
main.cpp:4:2: note: 'Base' has been explicitly marked deleted here
Base() = delete;
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
显然这种方式行不通。那么我如何修改代码以便它编译并且没有参数构造函数永远不会被调用而不会出错?
问题在于
Derive(Derive&& p) xxx { *this = std::move(p); }
Run Code Online (Sandbox Code Playgroud)
是在xxx
你有一个空的成员初始化列表的部分。这意味着编译器将为您插入一个基类,因为在执行构造函数体之前,所有成员都在成员初始化列表中进行了初始化。编译器生成的版本看起来像
Derive(Derive&& p) : Base() { *this = std::move(p); }
Run Code Online (Sandbox Code Playgroud)
你不能这样做,Base()
因为它被删除了。你想要的是
Derive(Derive&& p) : Base(std::move(p)) {}
Run Code Online (Sandbox Code Playgroud)
甚至更短
Derive(Derive&& p) = default;
Run Code Online (Sandbox Code Playgroud)