C++ std::move 从头开始分配 - 可维护性低
C++ std::move assignment from scratch - low maintainability
我喜欢新的 std::move
但担心它会降低我的程序可维护性。
据我所知,如果我创建 move constructor
或 move assignment operator=()
,我必须 从头开始编写 。这就是问题开始的地方。
代码版本 1
这是一个小 class:-
class B{
M shouldBeMove; //if it is copied, it is still correct (but prefer move)
C shouldBeCopy; //can be copied or moved, both are equal and ok
//wow, I don't even have to write this line for operator=():-
// this->shouldBeCopy = that.shouldBeCopy
}
B b1;
B b2=b1;
目前,B b2=b1
将同时复制 M
和 C
。没关系。
代码版本 2
现在我想使用std::move
的力量:-
class B{
M shouldBeMove; //now, the program is refactored that it must be moved
// M now has "M& operator=(M&& that)"
C shouldBeCopy;
B& operator=(B&& that){
this->shouldBeMove=std::move(that.shouldBeMove);
this->shouldBeCopy=that.shouldBeCopy; //<-- a bit tedious (1#)
// ... imagine that there are 10 variables to be copied ...
}
}
B b1;
B b2=std::move(b1);
还可以,就是有点乏味。 (1#)
代码版本 3
然后一个月后,我可能想添加一个新字段,例如C shouldBeCopy2
到 B
,我还必须在 operator=
中添加一行:-
B& operator=(B&& that){
this->shouldBeMove=std::move(that.shouldBeMove);
this->shouldBeCopy=that.shouldBeCopy;
this->shouldBeCopy2=that.shouldBeCopy2; //<--- new line
}
我觉得我是那种可能会忘记加上那句台词的类型。 (2#)
问题:
1#。如何让它不乏味?
2#。如何防止我的错误?
您应该遵循 rule of zero 并让编译器为您生成构造函数和赋值运算符。
但是当您需要实现可移动类型时,请确保同时实现移动赋值运算符 (T& operator=(T&&)
) 和移动构造函数 (T(T&&)
)。请遵循五法则并确保 class 具有正确的副本 constructor/move constructor/copy 赋值 operator/move 赋值 operator/destructor
#include <iostream>
using namespace std;
class M{
public: int database=0;
M& operator=(M&& other){
this->database=other.database;
other.database=0;
return *this;
}
M(M &&other) {
*this = std::move(other);
}
M (M& m)=default;
M ()=default;
~M() { /* free db */ }
};
class B{ // As rule of zero, you don't need to implement constructors and assignment operators
public: M shouldMove;
};
int main() {
B b;
b.shouldMove.database=5;
B b2=std::move(b);
std::cout<< b.shouldMove.database <<std::endl;
std::cout<< b2.shouldMove.database <<std::endl;
return 0;
}
我喜欢新的 std::move
但担心它会降低我的程序可维护性。
据我所知,如果我创建 move constructor
或 move assignment operator=()
,我必须 从头开始编写 。这就是问题开始的地方。
代码版本 1
这是一个小 class:-
class B{
M shouldBeMove; //if it is copied, it is still correct (but prefer move)
C shouldBeCopy; //can be copied or moved, both are equal and ok
//wow, I don't even have to write this line for operator=():-
// this->shouldBeCopy = that.shouldBeCopy
}
B b1;
B b2=b1;
目前,B b2=b1
将同时复制 M
和 C
。没关系。
代码版本 2
现在我想使用std::move
的力量:-
class B{
M shouldBeMove; //now, the program is refactored that it must be moved
// M now has "M& operator=(M&& that)"
C shouldBeCopy;
B& operator=(B&& that){
this->shouldBeMove=std::move(that.shouldBeMove);
this->shouldBeCopy=that.shouldBeCopy; //<-- a bit tedious (1#)
// ... imagine that there are 10 variables to be copied ...
}
}
B b1;
B b2=std::move(b1);
还可以,就是有点乏味。 (1#)
代码版本 3
然后一个月后,我可能想添加一个新字段,例如C shouldBeCopy2
到 B
,我还必须在 operator=
中添加一行:-
B& operator=(B&& that){
this->shouldBeMove=std::move(that.shouldBeMove);
this->shouldBeCopy=that.shouldBeCopy;
this->shouldBeCopy2=that.shouldBeCopy2; //<--- new line
}
我觉得我是那种可能会忘记加上那句台词的类型。 (2#)
问题:
1#。如何让它不乏味?
2#。如何防止我的错误?
您应该遵循 rule of zero 并让编译器为您生成构造函数和赋值运算符。
但是当您需要实现可移动类型时,请确保同时实现移动赋值运算符 (T& operator=(T&&)
) 和移动构造函数 (T(T&&)
)。请遵循五法则并确保 class 具有正确的副本 constructor/move constructor/copy 赋值 operator/move 赋值 operator/destructor
#include <iostream>
using namespace std;
class M{
public: int database=0;
M& operator=(M&& other){
this->database=other.database;
other.database=0;
return *this;
}
M(M &&other) {
*this = std::move(other);
}
M (M& m)=default;
M ()=default;
~M() { /* free db */ }
};
class B{ // As rule of zero, you don't need to implement constructors and assignment operators
public: M shouldMove;
};
int main() {
B b;
b.shouldMove.database=5;
B b2=std::move(b);
std::cout<< b.shouldMove.database <<std::endl;
std::cout<< b2.shouldMove.database <<std::endl;
return 0;
}