不可移动的结构?

时间:2014-09-13 18:30:07

标签: c++ c++11 move move-constructor

考虑这段代码,假设int state标记结构具有某种状态,并且该状态具有任何复杂性:

struct Object
{
private:
    int state = 0;

public:
    Object( Object&& other ):
      state( std::move( other.state ) )
    {}
};

struct ReferencingObject
{
private:
    Object& object;
    int     state = 0;

public:
    ReferencingObject( Object& object ):
      object( object )
    {}

    ReferencingObject( ReferencingObject&& other ):
      object( other.object ),
      state( std::move( other.state ) )
    {}
};

struct CannotMove
{
    Object              object;
    ReferencingObject   ref;

    CannotMove():
      object(),
      ref( object )
    {}

    CannotMove( CannotMove&& other ):
      object( std::move( other.object ) ),
      ref( std::move( other.ref ) )
    {}
};

1)关注CannotMove( CannotMove&& )移动构造函数,我认为我当前的实现是错误的,因为移动ReferencingObject实例会引用现在未定义的Object实例,因为它已经被移动了。但是,由于ReferencingObject struct包含自己的状态,我的结论是CannotMove没有正确的移动构造函数。我的结论是否正确?

2)现在假设我的结论是1)是正确的,CannotMove是一个相当复杂的模板类。复杂到足以获得实例的唯一合理方式(从用户的角度来看)是通过使用auto,例如:

auto cannotMoveInstance = createCannotMove();

createCannotMove()函数可以用允许编译器执行复制省略的方式编写,并完全解决1)这个特殊情况下的问题。但是,为了防止代码的用户意外移动CannotMove的实例,应将移动构造函数标记为已删除。但是,这会阻止编译器使用复制省略。我是否被迫放弃使用auto并直接通过

创建我的实例
CannotMove  instance;

修改1 ObjectReferencingObject的数据成员专用,以更好地反映典型的OOP编程。

1 个答案:

答案 0 :(得分:0)

您的班级不变量似乎 ref中的引用始终引用我自己的object

要保持此不变量,编写CannotMove的移动构造函数的正确方法是移动Object,然后自己构造ReferencingObject以引用您自己的对象。首先给ReferencingObject一个构造函数,该构造函数从ReferencingObject &&的状态移开,但将引用设置为不同的Object

ReferencingObject( ReferencingObject&& other, Object & obj ):
  object( obj ),
  state( std::move( other.state ) )
{}

然后:

CannotMove( CannotMove&& other ):
  object( std::move( other.object ) ),
  ref( std::move(other.ref), object )
{ }

如果你坚持要编写代码,那么没有,编写CannotMove的构造函数没有逻辑上正确的方法,因为你的ReferencingObject没有暴露任何接口来移动状态但是没有复制参考。有一些方法可以通过改变CannotMove的定义来解决这个问题(例如,将智能指针直接存储到Object而不是Object),但是因为你没有&# 39;我想改变其他任何东西,然后不,它就无法完成。

如果删除移动构造函数,则无法返回CannotMove,必须直接构造。