移动语义+引用成员的成员变量-解决方案和术语?

时间:2018-08-16 13:50:45

标签: c++ c++11 boost

我碰到过几次基本问题是,类C具有类A和类B的成员,而类B的构造函数引用了A。当您尝试std :: move C时,新的B获得了对旧A的引用,此举已被此举无效。

所以我的问题是:有这个名字吗?我一直在寻找解决方案,但找不到正确的搜索词。

过去,我的解决方案是“不要那样做”:让B拥有A,让C从B获得A。但是现在我遇到了无法解决的情况。相反,我必须在移动后修复引用。

我正在考虑通过编写对reference_wrapper的替换(通过移动操作使其无效)来强制执行此操作。但是在我做出承诺之前,我想知道是否存在现有的解决方案(例如,增强某些功能)。

以下是一些代码:

#include <iostream>
#include <functional>

struct A
{
    A( int x )
        : m_x( x )
        , m_ok( true )
    {
    }

    A( const A& ) = delete;
    A& operator=( const A& ) = delete;

    A( A&& other )
        : m_x( std::move( other.m_x ) )
        , m_ok( true )
    {
        other.m_ok = false;
    }

    A& operator=( A&& other )
    {
        m_x = std::move( other.m_x );
        m_ok = true;
        other.m_ok = false;
        return *this;
    }

    int m_x;
    bool m_ok;
};

struct B
{
    B( A& a )
        : m_a( a )
    {
    }

    std::reference_wrapper<A> m_a;
};

struct C
{
    C( int x )
        : m_a( x )
        , m_b( m_a )
    {
    }

    A m_a;
    B m_b;
};

int main()
{
    C oldc( 1 );
    C newc( std::move( oldc ) );
    std::cout << "C.A: " << newc.m_a.m_ok << " C.B.A: " << newc.m_b.m_a.get().m_ok << std::endl;
    return 0;
}

1 个答案:

答案 0 :(得分:2)

不知道此模式的名称,但是您不必为参考包装器定义一个替换。只需将move构造函数添加到struct C

struct C {
    C( int x )
        : m_a( x )
        , m_b( m_a ) { }
    C(C&& c) : m_a(std::move(c.m_a)), m_b(m_a) { }
    A m_a;
    B m_b;
};

请参见http://cpp.sh/374ca 输出为C.A:1 C.B.A:1

编辑:我刚刚意识到,甚至不需要B的移动ctor。只需对struct C进行此更改,就足以完成您要执行的操作。我已经更新了指向cpp.sh的链接。指向新的解决方案。