【发布时间】:2016-10-21 06:29:17
【问题描述】:
我看到很多代码在复制和交换方面实现了五规则,但我认为我们可以使用移动函数来替换交换函数,如下代码所示:
#include <algorithm>
#include <cstddef>
class DumbArray {
public:
DumbArray(std::size_t size = 0)
: size_(size), array_(size_ ? new int[size_]() : nullptr) {
}
DumbArray(const DumbArray& that)
: size_(that.size_), array_(size_ ? new int[size_] : nullptr) {
std::copy(that.array_, that.array_ + size_, array_);
}
DumbArray(DumbArray&& that) : DumbArray() {
move_to_this(that);
}
~DumbArray() {
delete [] array_;
}
DumbArray& operator=(DumbArray that) {
move_to_this(that);
return *this;
}
private:
void move_to_this(DumbArray &that) {
delete [] array_;
array_ = that.array_;
size_ = that.size_;
that.array_ = nullptr;
that.size_ = 0;
}
private:
std::size_t size_;
int* array_;
};
我认为是这段代码
- 异常安全
- 需要更少的输入,因为许多函数只需调用 move_to_this(),并且复制赋值和移动赋值统一在一个函数中
- 比复制和交换更有效,因为交换涉及 3 个分配,而这里只有 2 个,并且此代码不会遇到This Link 中提到的问题
我说的对吗?
谢谢
编辑:
- 正如@Leon 指出的那样,可能需要一个用于释放资源的专用函数,以避免
move_to_this()和析构函数中的代码重复 -
正如@thorsan 所指出的,出于极端的性能考虑,最好将DumbArray& operator=(DumbArray that) { move_to_this(that); return *this; }分隔为DumbArray& operator=(const DumbArray &that) { DumbArray temp(that); move_to_this(temp); return *this; }(感谢@MikeMB)和DumbArray& operator=(DumbArray &&that) { move_to_this(that); return *this; },以避免额外的移动操作添加一些调试打印后,我发现
DumbArray& operator=(DumbArray that) {}中没有额外的移动,当你调用它作为移动赋值时 正如@Erik Alapää 所指出的,在
move_to_this()中的delete之前需要进行自分配检查
【问题讨论】:
-
比较适合Code Review?
-
代码不是异常安全的,因为至少 new 和 delete 可以抛出。
-
@Resurrection,我所说的“异常安全”并不是说它不抛出异常,而是即使抛出异常,它也不会破坏任何东西并使现有对象无效
-
题外话可能你还没有实现这五个,你实现的赋值运算符既不是复制也不是移动,复制:
DumbArray& operator=(DumbArray& that)和移动DumbArray& operator=(DumbArray&& that)。而且copy和move不能一样,所以move_to_this不能用于copy和move。 -
有没有计划将元素类型从
int更改为一些非平凡的类类型?