2013-04-30 111 views
9

我有一个类,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()) 
{ 
} 

和一个类,PlayerMoveComponen吨,包含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变量,我认为以下两件事情之一是应该发生:

  1. PlayerInputComponent的举动构造函数用于初始化playerInputComponent成员变量。
  2. 这一举措被编译器忽略了。

然而,的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实例,而不是引用,可以摆脱该错误,但我不明白为什么 - 我测试并验证了,只要您提供了参考成员就可以使用参考成员移动构造对象自己的移动构造函数,那么交易是什么?

+0

@MooingDuck:我看不出如何回答这个问题。我很确定这是MSVC中的一个错误。 – 2013-05-01 00:03:47

+1

@JesseGood:[哦你是对的](http://coliru.stacked-crooked.com/),我误解了部分代码。然后它是[我的这个错误报告](https://connect.microsoft。com/VisualStudio/feedback/details/778513/msvc10-using-copy-constructor-instead-of-move):P – 2013-05-01 00:15:05

+0

上述类的*声明*被分解为只包含可重复的结果特别是'PlayerMoveComponent' – WhozCraig 2013-05-01 00:25:40

回答

1

对不起,如果这不能真正回答你的问题,我只想对你的问题的表面复杂性作出反应。如果可以的话,千万不要这么简单:

/********************  **********  ********************/ 

class C {}; 
class B; 



class A 
{ 
public: 

    A(): _b(nullptr), _c(nullptr) {} 
    A(B *b, C *c): _b(b), _c(c) {} 
    A(A&& a): _b(a._b), _c(a._c) {} 

private: 

    C *_c; 
    B *_b; 
}; 



class B 
{ 
public: 

    B(/* other parameters */ C *c): _a(A(this,c)) {} 

private: 

    A _a; 
}; 


    /********************  **********  ********************/ 


int main() 
{ 
    C c; 
    B b(&c); 
} 

然而实现同样的事情呢?我没有反对在C++ 11中使用新功能,如std::unique_ptr,但恕我直言,确保指针永远不能从两个地方解除引用不应该是运行时检查的问题(除非可能在极少数情况下),但设计的问题..不应该吗?

+0

我真的同意你的看法,但我认为不使用原始指针的主要原因是对谁使用原始指针有一定的安全性。例如在你的代码中,我可以传递一个c指针给你的B类,并且在这个调用之后删除它! (BOOM ...稍后会崩溃)。如上所述使用unique_ptr可以防止这种情况发生,因为控制权将传递给新的B实例,并且没有人可以删除它。 – 2013-05-07 21:34:47

+0

Ahn ...顺便说一句,我不知道是否unique_ptr在解引用时做任何类型的检查...如果你创建一个全新的(nullptr)并尝试访问它,它将像任何指针一样崩溃。当你想要确定谁是所有者时它是有用的,并且它必须是一个所有者(唯一)。 – 2013-05-07 21:38:49

+0

@JulioRaffaine非常感谢这些评论!:)我的意思是解除引用是这个;你想要一个'unique_ptr'的唯一原因是你不想让其他人访问它。 AFA的删除关注,足够有趣,我认为它应该更简单,如果你打算使用'unique_ptr',并且你最终不会:这里唯一包含唯一c指针的类是A,所以逻辑上应该是A在析构函数中删除为c分配的内存,并在它被简单复制时将其“取消”。 – Sheljohn 2013-05-07 21:53:02

1

如果使用=初始化新对象,默认情况下会触发复制构造函数。 要触发移动构造函数,你需要改变operator=的行为 你可以找到一个例子here 希望我帮了你。

相关问题