我什么时候需要交换功能
When do I need a swap function?
当我编写拥有资源的类时,我非常习惯编写简单的交换功能来简化传输/复制资源的过程。以下代码是一个微不足道的示例:
class MyArray {
public:
MyArray(size_t size) :
_array(size ? new int[size] : nullptr),
_size(size)
{
}
MyArray(const MyArray & mv) :
MyArray(mv._size)
{
if(mv._size) std::copy(mv._array, mv._array + mv._size, _array);
}
static void friend swap(MyArray & mv1, MyArray & mv2) noexcept {
std::swap(mv1._array, mv2._array);
std::swap(mv1._size, mv2._size);
}
MyArray(MyArray && mv) {
swap(*this, mv);
}
MyArray & operator=(MyArray mv) {
swap(*this, mv);
return *this;
}
~MyArray() noexcept {
delete[] _array;
}
int & operator[](size_t index) {
if(index >= _size) throw std::exception("Index Out of Bounds!");
return _array[index];
}
const int & operator[](size_t index) const {
if(index >= _size) throw std::exception("Index Out of Bounds!");
return _array[index];
}
size_t size() const {
return _size;
}
private:
int * _array;
size_t _size;
};
但是,我可以选择[等效地]这样的代码:
class MyArray {
public:
MyArray(size_t size) :
_array(size)
{
}
int & operator[](size_t size) {
if(index >= size()) throw std::exception("Index Out of Bounds!");
return _array[index];
}
const int & operator[](size_t index) const {
if(index >= size()) throw std::exception("Index Out of Bounds!");
return _array[index];
}
size_t size() const {
return _array.size();
}
private:
std::vector<int> _array;
};
和在第二个代码中,swap
功能默认为正常std::swap
行为(即将第一个构造到临时,将第二个移动到第一个,然后将临时分配到第二个),然后将其移动到第二个),应该与第一个代码相同(在设计级别上)。
我当时的问题是我必须明确定义swap
函数的情况是什么,但不是我只是尝试重新使用代码的情况(例如来自第一个示例代码)?是否有明显的(或不太明显的)方案,即使我的代码中没有明确管理资源,我也会客观地从swap
函数中受益?我应该只为我编写的每个[Move-Constructtructs]类自动使用swap
函数,还是可以通过此操作来浪费代码?
如果您不定义自己的交换操作,则using std::swap; swap(lhs, rhs);
将其编译为大致:
auto tmp = std::move(rhs);
rhs = std::move(lhs);
lhs = std::move(tmp);
这会导致3个动作发生,并且需要一个竞争的临时对象。
如果移动分配和移动构造运算符具有强大的异常保证,则此交换的异常保证弱。如果移动分配和移动构造运算符是不可以的,那么此交换也是如此。
相比之下,会员互换可以在不一致的状态下留下对象。如果您的代码可以处理此操作,则意味着您永远不必创建完整的临时对象。因此,如果您可以处理部分交换的组件,并且完整的临时对象(由移动创建)有一定的成本,那么会员交换的速度可能更快。
但是,如果一切都不是(通常是互换/移动),则结果交换操作在逻辑上等效。
您的第二个MyArray
实际上没有管理资源。这是由std::vector
处理的,它确实在您的第一个代码中写了大部分代码。
零的规则是,不管理资源的类不需要编写任何副本或移动分配或施工,也不需要驱动器。这样的课程可能也不需要交换。
确实写副本/移动和破坏的类,管理资源的类,可以使用交换来做到这一点。否则, std::swap
做得不错。
旁
friend auto mytie( MyArray& self ) noexcept {
return std::tie(self.array, self.size);
}
然后交换变为:
friend void swap( MyArray& lhs, MyArray& rhs ) noexcept {
std::swap( mytie(lhs), mytie(rhs) );
}
将您的"重复成员名称"的样板计数减少1。
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 多态性和功能结合
- 带内存和隔离功能的SQLite
- 在CMakeLists.txt的安装功能中使用.cmake文件有什么用
- C++ - 没有自定义交换功能的移动分配运算符?
- 不正确的比较和交换计数器输出用于快速排序功能
- 如何在专门使用交换功能时修复 gcc8 的编译错误/
- 实现交换/复制功能:有没有更好的方法
- 获取交换功能的分段错误11
- 编写一个功能,该函数将使用框架交换两个整数
- 在C 类中超载交换功能
- 交换功能 - 指针 - 混乱
- 我什么时候需要交换功能
- 第一个交换功能有什么问题?
- std::ref 和交换功能似乎不能很好地协同工作
- 发出写入交换功能
- 交换功能出现分段故障
- 我如何使交换功能更快在c++
- 基本值交换功能
- 基于ai+b mod n的交换功能