移动语义+对成员成员变量的引用 - 解决方案和命名法?
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&&) = delete
。这将自动停止 struct C
在没有明确定义移动构造函数的情况下被移动。尝试移动 C
时会出现编译时错误。以上是关于移动语义+对成员成员变量的引用 - 解决方案和命名法?的主要内容,如果未能解决你的问题,请参考以下文章
第6章 移动语义和enable_if:6.2 特殊成员函数模板