我的移动构造函数和移动赋值运算符写得好吗?
Are my move constructor and move assignment operator written well?
我要在此结构中添加移动构造函数和移动赋值运算符。
谁能告诉我写得好不好?
当我 运行 没有这两种方法的代码时它运行正常,但是当我添加这两种方法时它不起作用。
非常感谢
struct Data {
Data() = default;
Data(const unsigned int _x) : data(new unsigned char[_x]), size(_x) {}
Data(const Data &_d) : data(new unsigned char[_d.size]), size(_d.size) {
memcpy(data, _d.data, _d.size);
}
~Data() {
delete[] data;
size = 0;
};
Data& operator=(const Data &_d) {
if (this == &_d) {
return *this;
}
unsigned char *tmp(new unsigned char[_d.size]);
memcpy(tmp, _d.data, _d.size);
delete[] data;
data = tmp;
size = _d.size;
return *this;
}
这是我的移动构造函数,我应该先删除数据吗?如果大小不相等,则分配新大小的数据?
Data(Data &&_d)
{
data = _d.data;
_d.data = nullptr;
size = _d.size;
_d.size = 0;
}
这是我的移动赋值运算符
Data& operator=(Data&& _d)
{
if (this != &_d)
{
delete[] data;
data = _d.data;
_d.data = nullptr;
size = _d.size;
_d.size = 0;
}
return *this;
}
unsigned char *data = nullptr;
unsigned int size = 0;
};
您在 class 中提供了开始和结束方法。可能您想使用 STL。在这种情况下,如果你想提供强大的异常保证,你应该添加 noexcept 。如果 STL 容器是 noexcept(false).
,它们将不会使用您的移动 constructors/assignments
Data& operator=(Data&& _d) noexcept
{
if (this != &_d)
{
delete[] data;
data = _d.data;
_d.data = nullptr;
size = _d.size;
_d.size = 0;
}
return *this;
}
Data(Data &&_d) noexcept
{
data = _d.data;
_d.data = nullptr;
size = _d.size;
_d.size = 0;
}
An STL container can only use the move constructor in it's resizing
operation if that constructor does not break its strong exception
safety guarantee. In more plain language, it wont use the move
constructor of an object if that can throw an exception. This is
because if an exception is thrown in the move then the data that was
being processed could be lost, where as in a copy constructor the
original will not be changed.
您的代码是正确的。
但是还有一种模式可以使用 std::swap:
来实现移动分配
Data& operator=(Data&& _d)
{
std::swap(data, _d.data);
std::swap(s, _d.size);
return *this;
}
此处旧数据会在调用_d
析构函数时释放。
这不是一个“更正确的方式”,但它更容易编写并且更少space忘记正确处理资源。
移动构造函数可以重用移动赋值:
Data(Data&& _d)
: this()
{
*this = std::move(_d);
}
同样,这不是更好的方法,但可以减少重复代码的数量。
我要在此结构中添加移动构造函数和移动赋值运算符。 谁能告诉我写得好不好? 当我 运行 没有这两种方法的代码时它运行正常,但是当我添加这两种方法时它不起作用。 非常感谢
struct Data {
Data() = default;
Data(const unsigned int _x) : data(new unsigned char[_x]), size(_x) {}
Data(const Data &_d) : data(new unsigned char[_d.size]), size(_d.size) {
memcpy(data, _d.data, _d.size);
}
~Data() {
delete[] data;
size = 0;
};
Data& operator=(const Data &_d) {
if (this == &_d) {
return *this;
}
unsigned char *tmp(new unsigned char[_d.size]);
memcpy(tmp, _d.data, _d.size);
delete[] data;
data = tmp;
size = _d.size;
return *this;
}
这是我的移动构造函数,我应该先删除数据吗?如果大小不相等,则分配新大小的数据?
Data(Data &&_d)
{
data = _d.data;
_d.data = nullptr;
size = _d.size;
_d.size = 0;
}
这是我的移动赋值运算符
Data& operator=(Data&& _d)
{
if (this != &_d)
{
delete[] data;
data = _d.data;
_d.data = nullptr;
size = _d.size;
_d.size = 0;
}
return *this;
}
unsigned char *data = nullptr;
unsigned int size = 0;
};
您在 class 中提供了开始和结束方法。可能您想使用 STL。在这种情况下,如果你想提供强大的异常保证,你应该添加 noexcept 。如果 STL 容器是 noexcept(false).
,它们将不会使用您的移动 constructors/assignmentsData& operator=(Data&& _d) noexcept
{
if (this != &_d)
{
delete[] data;
data = _d.data;
_d.data = nullptr;
size = _d.size;
_d.size = 0;
}
return *this;
}
Data(Data &&_d) noexcept
{
data = _d.data;
_d.data = nullptr;
size = _d.size;
_d.size = 0;
}
An STL container can only use the move constructor in it's resizing operation if that constructor does not break its strong exception safety guarantee. In more plain language, it wont use the move constructor of an object if that can throw an exception. This is because if an exception is thrown in the move then the data that was being processed could be lost, where as in a copy constructor the original will not be changed.
您的代码是正确的。
但是还有一种模式可以使用 std::swap:
来实现移动分配Data& operator=(Data&& _d)
{
std::swap(data, _d.data);
std::swap(s, _d.size);
return *this;
}
此处旧数据会在调用_d
析构函数时释放。
这不是一个“更正确的方式”,但它更容易编写并且更少space忘记正确处理资源。
移动构造函数可以重用移动赋值:
Data(Data&& _d)
: this()
{
*this = std::move(_d);
}
同样,这不是更好的方法,但可以减少重复代码的数量。