异常安全移动操作员
Exception safe move operator
我通常(试图)使用复制交换习惯用法编写异常安全的复制赋值运算符,我想知道在编写移动赋值运算符时是否应该注意异常。以下是一个副本分配操作员的示例:
template<class T>
CLArray<T>&
CLArray<T>::operator=( const CLArray& rhs )
{
CLArray tmp( rhs );
std::swap( size_, tmp.size_ );
std::swap( data_, tmp.data_ );
return *this;
}
但是搬家任务呢?我的意思是,如果在THIS移动操作期间在代码中的其他地方抛出异常,我将失去两个对象的状态,对吗?所以我必须先创建一个本地副本,然后删除除新创建的CLArray
之外的所有内容。。。
template <class T>
CLArray<T>&
CLArray<T>::operator=( CLArray<T>&& rhs )
{
size_ = rhs.size_;
data_ = std::move( rhs.data_ );
return *this;
}
请注意,data_
是一个std::向量,感谢您的回答!
事实上,如果move构造函数可能抛出异常,则很难或不可能提供异常保证。
我建议像标准库那样做:记录某些操作只有在T
的move构造不抛出的情况下才有异常保证(或者,在某些情况下,只允许)。通过复制对象来确保这种保证会破坏移动分配对所有类型的好处,而不仅仅是可能抛出的(非常罕见的)类型。
无论如何,您应该添加一个swap
成员函数,并利用(复制/移动)赋值运算符中的(复制/移)构造函数。(把不能扔的操作放在可能扔的操作之后。)
示例(为了简洁起见,在类中内联):
template<typename T>
class CLArray {
public:
void swap( CLArray& other )
{
std::swap( data_, other.data_ );
std::swap( size_, other.size_ );
}
CLArray( const CLArray& other )
: data_( other.data_ ), size_( other.size_ )
{
}
CLArray& operator=( const CLArray& rhs )
{
CLArray( rhs ).swap( *this );
return *this;
}
CLArray( CLArray&& other )
: data_( std::move( other.data_ ) )
{
size_ = other.size_;
other.size_ = 0;
}
CLArray& operator=( CLArray&& rhs )
{
CLArray( std::move( rhs ) ).swap( *this );
return *this;
}
// ...
private:
std::vector<T> data_;
std::size_t size_;
};
参见C9讲座:Stephan T.Lavavej-标准模板库(STL),第9页,共n页(右值参考文献)(视频和STL的备注以及备注中的代码)。
你可能还想阅读Dave Abrahams的文章《你的下一个任务…》和《异常移动!》!。
相关文章:
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- C / C++ 移位/偏移/向左或向右移动位图?
- MSVC将仅移动结构参数解释为指针
- 自定义先决条件对移动分配运算符有效吗
- 返回值优化:显式移动还是隐式
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- <<操作员在下面的行中工作
- 可以使用移动语义更改或改进此C++代码吗?
- 使lambda不可复制/不可移动
- c++在使用指针时移动语义
- 将QGraphicsItem的移动区域限制在多边形区域内
- 分开副本/移动分配操作员
- 位移动操作员无视数据大小
- 操作员移动装载的工作原理
- RVO和NRVO优化+C++11移动操作员
- 异常安全移动操作员