c++移动运算符类成员

c++ move operators class members

本文关键字:成员 运算符 移动 c++      更新时间:2023-10-16

我正在围绕一个使用句柄的库编写一个小包装。

这个库的基本用途是:

int handle;
createHandle( 1, &handle )
doSomethingWithHandle( handle );
// ...
destroyHandle( handle );

我按照RAII原则制作了一个包装类:

Handle::Handle()
{
    createHandle( 1, &m_handle );
}
Handle::~Handle()
{
    if( m_handle!= 0 )
        destroyHandle( m_handle );
}
Handle::Handle( Handle&& h ) :
    m_handle( h.m_handle )
{
    h.m_handle = 0;
}
Handle& Handle::operator=( Handle&& h )
{
    m_handle = h.m_handle;
    h.m_handle = 0;
    return *this;
}
// copy constructor and copy assignment operator are explicitely deleted

然而,它是有效的,很多类都依赖于这些包装器,这意味着每次类有Handle成员时,我都必须明确地编写移动构造函数/移动赋值运算符:

SomeClass::SomeClass( SomeClass&& s ) :
    m_handle( std::move( s.m_handle ) )
{
}
SomeClass& SomeClass::SomeClass( SomeClass&& s )
{
    m_handle = std::move( s.m_handle );
    return *this;
}

当然,这并不难做到,但我想知道是否有办法避免这种情况,因为这有很多多余的代码。

如果这不可能,为什么编译器不生成move运算符?让我们采取以下路线:

SomeClass a;
m_vector.push_back( a );

在这种情况下,someclass是不可复制的,因此编译器将出现错误,因为a.m_handle删除了复制运算符。所以这意味着我们必须移动它们。但如果我们这样做了,难道不意味着我们想移动每个成员(如果我们不能复制他们(吗?

编辑:我刚刚尝试了一些东西,它似乎有效,只需使用默认值声明移动运算符。我想这就是要走的路。但"为什么"的问题仍然存在。

第2版:的另一个例子

class Test
{
public:
    Test()
    {
        m_vec.resize( 10 );
    }
    Test( const Test& ) = delete;
    Test& operator=( const Test& ) = delete;
    //Test( Test&& ) = default;
    //Test& operator=( Test&& ) = default;
    void cout()
    {
        std::cout << m_vec.size() << std::endl;
    }
private:
    std::vector< int > m_vec;
};
int main()
{
    Test a;
    std::vector< Test > v;
    v.push_back( std::move( a ) );
    v[ 0 ].cout();
}

我必须明确地编写移动构造函数/移动赋值运算符:

这就是你错的地方。要么根本不写它们,让编译器来写,要么=default;它们。

SomeClass a;
m_vector.push_back( a );

你做错了,一定是:

SomeClass a;
m_vector.push_back( std::move(a) );