C++ 异常安全移动运算符

C++ 异常安全移动运算符,c++,move,C++,Move,我通常(尝试)使用复制交换习惯用法编写异常安全的复制分配运算符,我想知道在编写移动分配运算符时是否应该关注异常。 下面是复制赋值运算符的示例: template<class T> CLArray<T>& CLArray<T>::operator=( const CLArray& rhs ) { CLArray tmp( rhs ); std::swap( size_, tmp.size_ ); std::swap( da

我通常(尝试)使用复制交换习惯用法编写异常安全的复制分配运算符,我想知道在编写移动分配运算符时是否应该关注异常。 下面是复制赋值运算符的示例:

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;
}

请注意,
data\uu
是一个std::vector,谢谢您的回答

事实上,如果move构造函数可能抛出异常,则很难或不可能提供异常保证


我建议像标准库那样做:记录某些操作只有在
T
的move构造没有抛出时才有异常保证(或者,在某些情况下,仅允许)。通过复制对象来确保保证会破坏所有类型移动分配的好处,而不仅仅是可能抛出的(非常罕见的)类型。

无论如何,您应该添加一个
交换
成员函数,并利用(复制/移动)分配操作符中的(复制/移动)构造函数。(并将不能抛出的操作放在可能抛出的操作之后。)

示例(为了简洁起见,在类中内联):

模板
克拉瑞班{
公众:
无效交换(CLArray和其他)
{
std::swap(data_u,other.data_u);
std::swap(size_u,other.size_u);
}
克拉雷(康斯特·克拉雷和其他)
:data_u(other.data_u)、size_u(other.size_u)
{
}
CLArray和运算符=(常量CLArray和rhs)
{
CLArray(rhs).swap(*本);
归还*这个;
}
CLArray(CLArray和其他)
:数据(std::move(other.data)
{
尺寸=其他尺寸;
其他尺寸=0;
}
CLArray&运算符=(CLArray&&rhs)
{
CLArray(std::move(rhs)).swap(*此);
归还*这个;
}
// ...
私人:
std::矢量数据;
标准:尺寸;
};
请参阅(视频和STL的备注以及备注中的代码)


您可能还想阅读Dave Abrahams的文章和。

谢谢您的回答,我完全明白为什么创建副本对于移动任务来说是愚蠢的。
template <class T>
CLArray<T>&
CLArray<T>::operator=( CLArray<T>&& rhs )
{
    size_ = rhs.size_;
    data_ = std::move( rhs.data_ );
    return *this;
}
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_;
};