这个成语是什么,什么时候应该使用?它解决了哪些问题?当使用C++ 11时,成语是否会改变?
虽然在许多地方已经提到过,但我们没有任何单一的"它是什么"问题和答案,所以在这里.以下是前面提到的地方的部分列表:
c++ c++-faq copy-constructor assignment-operator copy-and-swap
在类的赋值运算符中,通常需要检查所分配的对象是否是调用对象,这样就不会搞砸了:
Class& Class::operator=(const Class& rhs) {
if (this != &rhs) {
// do the assignment
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
移动赋值运算符需要相同的东西吗?是否有过这样的情况this == &rhs?
? Class::operator=(Class&& rhs) {
?
}
Run Code Online (Sandbox Code Playgroud) 通过使用Copy&Swap习语,我们可以轻松实现具有强大异常安全性的副本分配:
T& operator = (T other){
using std::swap;
swap(*this, other);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
但是这需要T是可交换的.如果std::is_move_constructible_v<T> && std::is_move_assignable_v<T> == true感谢,自动哪种类型std::swap.
我的问题是,使用"复制和移动"成语有没有任何缺点?像这样:
T& operator = (T other){
*this = std::move(other);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
只要你实现了move-assignment,T因为很明显你最终会得到无限递归.
这个问题不同于复制和交换成语是否应该成为C++ 11中的复制和移动成语?因为这个问题更通用,并且使用移动赋值运算符而不是手动移动成员.这避免了在链接线程中预测答案的清理问题.
我看到许多代码在复制和交换方面实现了五个规则,但我认为我们可以使用移动函数来替换交换函数,如下面的代码所示:
#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_ …Run Code Online (Sandbox Code Playgroud) 通常,给定某种类型T,要实现复制和移动赋值,需要两个函数
T& operator=(T&&) { ... }
T& operator=(const T&) { ... }
Run Code Online (Sandbox Code Playgroud)
最近,我逐渐意识到单一的就足够了
T& operator=(T v) {
swap(v);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
此版本利用了复制/移动构造函数.赋值是复制还是移动取决于v构造方式.这个版本甚至可能比第一个版本更快,因为pass-by-value允许更多的空间用于编译器优化[1].那么,即使标准库使用它,第一个版本优于第二个版本的优势是什么?
[1]我想这解释了为什么标签和函数对象在标准库中按值传递.