我的任务是在 C++ 中为机器人游戏实现移动语义(移动构造函数和移动赋值运算符)。
我收到一些反馈,说在使用移动语义时我应该从另一个对象“窃取”资源,所以我尝试这样做,但后来有人说这是一个浅拷贝,并且 std::move 不是必需的。还有人问当 GameState 超出范围时会发生什么并且可能无法正确处理。
当我从一个级别转到下一个级别时,mainwindow.cpp 中有一行使用赋值运算符。从未使用过移动构造函数,只需正确实现即可。
主窗口.cpp:
gameState = GameState(numberOfRobots); // constructor called
游戏状态.cpp:
// Constructor.
GameState::GameState(int numberOfRobots) {
for (int i = 0; i < numberOfRobots; i++) {
Robot* robot = new Robot();
units.push_back(robot);
}
teleportHero();
}
// Move constructor. Is never called.
GameState::GameState(GameState&& other) noexcept {
units = move(other.units);
}
// Move assignment operator. Is called when going from one level to the next level (gameState = ...)
GameState& GameState::operator=(GameState&& other) noexcept {
if (this != &other) {
for (Unit* unit : units)
delete unit;
// steal all units from other to this GameState using move()
units = move(other.units);
}
// returns a reference to the object into which the data was moved
return *this;
}
我需要有关如何编写移动构造函数和移动赋值运算符的帮助。如果需要更多代码,请告诉我。
根据四分半规则,你的移动构造函数和移动赋值运算符应该只
swap
一个对象的内容与另一个对象的内容,这提供了强大的异常安全保证,并防止像 self 这样的意外错误移动作业。
#include <vector>
struct foo; // forward declaration
void swap(foo& a, foo& b) noexcept;
struct foo
{
std::vector<int> vec;
int* data;
foo(): vec(), data(nullptr) {}
foo(foo&& other): foo() // call default constructor
{
swap(*this, other);
}
foo& operator=(foo&& other)
{
swap(*this, other);
return *this;
}
};
void swap(foo& a, foo& b) noexcept
{
std::swap(a.vec,b.vec);
std::swap(a.data,b.data);
}
这需要一个默认构造函数,将对象置于已定义的状态(所有指针应为空,所有向量应为空)。