【发布时间】:2013-04-25 00:09:04
【问题描述】:
我有课,PlayerInputComponent:
.h:
class PlayerInputComponent
{
public:
PlayerInputComponent(PlayerMoveComponent& parentMoveComponent_, std::unique_ptr<IRawInputConverter> inputConverter_);
PlayerInputComponent(PlayerInputComponent&& moveFrom);
void update();
private:
std::unique_ptr<IRawInputConverter> inputConverter;
PlayerMoveComponent& parentMoveComponent;
};
}
.cpp:
PlayerInputComponent::PlayerInputComponent(PlayerMoveComponent& parentMoveComponent_, std::unique_ptr<IRawInputConverter> inputConverter_) :
parentMoveComponent(parentMoveComponent_),
inputConverter(std::move(inputConverter_))
{
}
PlayerInputComponent::PlayerInputComponent(PlayerInputComponent&& moveFrom) :
parentMoveComponent(moveFrom.parentMoveComponent),
inputConverter(moveFrom.inputConverter.release())
{
}
还有一个类PlayerMoveComponent,它包含一个PlayerInputComponent 成员并使用作为参数传递的std::unique_ptr 对其进行初始化。它的构造函数:
PlayerMoveComponent::PlayerMoveComponent(/* other parameters */ std::unique_ptr<IRawInputConverter> inputConverter) :
//other initializations
inputComponent(PlayerInputComponent(*this, std::move(inputConverter)))
{
}
我为PlayerInputComponent 类定义了自己的移动构造函数,因为我的理解是不会为包含引用成员的类构造默认移动构造函数。在这种情况下,尽管我知道引用将在 PlayerInputComponent 对象的生命周期内保持在范围内。
由于我正在从临时初始化PlayerMoveComponent 的inputComponent 变量,我相信应该会发生以下两件事之一:
-
PlayerInputComponent的移动构造函数用于初始化playerInputComponent成员变量。 - 编译器忽略了移动。
然而,Visual Studio 2012 吐出这一点:
error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1> with
1> [
1> _Ty=SDLGame::IRawInputConverter
1> ]
1> c:\program files\microsoft visual studio 11.0\vc\include\memory(1447) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1> with
1> [
1> _Ty=SDLGame::IRawInputConverter
1> ]
1> This diagnostic occurred in the compiler generated function 'PlayerInputComponent::PlayerInputComponent(const PlayerInputComponent &)'
为什么在这里调用复制构造函数?使 PlayerInputComponent 类的 parentMoveComponent 成员成为常规 ParentMoveComponent 实例,而不是引用,可以消除错误,但我不明白为什么 - 我已经测试并验证了使用引用成员构造对象的移动工作只要您提供自己的移动构造函数,那有什么关系?
【问题讨论】:
-
@MooingDuck:我不明白这如何回答这个问题。我很确定这是 MSVC 中的一个错误。
-
@JesseGood: oh you're right,我误读了部分代码。然后是This bug report of mine:P
-
上述类的声明,被精简为只包含可重现的结果(这似乎不太难)也很高兴看到,特别是@ 987654340@
-
@yngum:假设
inputComponent是PlayerInputComponent,然后你告诉它从参数构造PlayerInputComponent,然后从那个临时移动构造inputComponent。大概你的意思是inputComponent(*this, std::move(inputConverter))。 -
@JonathanWakely,是的,它可以从右值移动,但在不知道
inputComponent实际上是什么类型的情况下,我不知道右值可用于在不调用副本的情况下对其进行初始化.特别是,如果inputComponent是一个包含可复制但不可移动成员的类,它也将(默认情况下)可复制但不可移动,这意味着移动构造函数实际上是一个复制构造函数。根据inputComponent的类型提供的构造函数,可能会出现类似的副作用。这就是为什么我认为我们需要知道它的类型,而我在 OP 中看不到它。
标签: c++ c++11 move-semantics