移动语义+对成员成员变量的引用 - 解决方案和命名法?

Posted

技术标签:

【中文标题】移动语义+对成员成员变量的引用 - 解决方案和命名法?【英文标题】:Move semantics + reference to member's member variable - solutions and nomenclature? 【发布时间】:2018-08-16 13:50:45 【问题描述】:

我遇到过几次的基本问题是,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】:

不知道此模式的名称,但您不必为引用包装器定义替代品。只需将移动构造函数添加到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 的链接。指向新的解决方案。

【讨论】:

当然,那会很好。我真正想要防止的是人们不小心写了一个 C 而没有意识到他们需要那个移动构造函数。 (即,这就是刚刚发生的事情,这就是我正在研究这个的原因?)我在想给 B 一个不同类型的引用,它会在移动中失效。 这是直截了当的。只需在您的struct B 中输入B(B&amp;&amp;) = delete。这将自动停止 struct C 在没有明确定义移动构造函数的情况下被移动。尝试移动 C 时会出现编译时错误。

以上是关于移动语义+对成员成员变量的引用 - 解决方案和命名法?的主要内容,如果未能解决你的问题,请参考以下文章

第6章 移动语义和enable_if:6.2 特殊成员函数模板

C++11常用知识点(上)

在C中参考命名的结构成员直接初始化或分配变量数组的结构成员?

返回对成员变量数据的引用的开销

是否有对成员变量的任何引用? [关闭]

使用移动语义在构造函数中初始化类成员