考虑这段代码,假设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 :Object
和ReferencingObject
的数据成员专用,以更好地反映典型的OOP编程。
答案 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
,必须直接构造。