2014-11-25 128 views
1

这个新类的东西,很可能做错了什么,而是 -C++交换的unique_ptr的

我有3名成员

std::unique_ptr<Gun> currentWeapon; 
std::unique_ptr<Gun> weaponSlotOne; 
std::unique_ptr<Gun> weaponSlotTwo; 

枪是具有其他派生类如PistolSMG一个基类。

我在做的是将weaponSlotOneweaponSlotTwo设置为两种不同的枪,然后将currentWeapon设置为第一个武器。

weaponSlotOne.reset(new DevPistol()); 
weaponSlotTwo.reset(new AutoDevPistol()); 
currentWeapon = std::move(weaponSlotOne); 

和我有一个switchWeapons方法,做这个:

void Player::switchWeapons() { 
    if(currentWeapon == weaponSlotOne) { 
     currentWeapon = std::move(weaponSlotTwo); 
    } 
    else { 
     currentWeapon = std::move(weaponSlotOne); 
    } 
} 

这似乎破坏/解除分配双枪出于某种原因。我不太确定发生了什么问题。

+1

'unique_ptr'在这种情况下没有意义 – 2014-11-25 01:53:04

+0

也许:http://en.cppreference.com/w/cpp/memory/unique_ptr/release? – Galik 2014-11-25 01:53:05

回答

1

问题是,在对象上调用std::move后,对象处于不确定状态,除了销毁或分配给对象之外,您无法安全地对对象执行任何操作。

在你的情况下,在做currentWeapon = std::move(weaponSlotOne);,weaponSlotOne是不确定的,所以当你测试currentWeapon == weaponSlotOne时,你可能会得到任何结果。可能这是错误的(weaponSlotOne将为空),所以你只需将它复制到currentWeapon,放下那里(删除它)。

问题是,你想要做什么?如果你想两种武器,并要跟踪其中一个是最新的,它可能会更有意义的事:

std::unique_ptr<Gun> *currentWeapon; 
std::unique_ptr<Gun> weaponSlotOne; 
std::unique_ptr<Gun> weaponSlotTwo; 

weaponSlotOne.reset(new DevPistol()); 
weaponSlotTwo.reset(new AutoDevPistol()); 
currentWeapon = &weaponSlotOne; 

void Player::switchWeapons() { 
    if(currentWeapon == &weaponSlotOne) { 
     currentWeapon = &weaponSlotTwo; 
    } 
    else { 
     currentWeapon = &weaponSlotOne; 
    } 
} 

或者更简单地说:

std::unique_ptr<Gun> weaponSlot[2]; 
int currentWeapon = 0; 

void Player::switchWeapons() { 
    currentWeapon ^= 1; 
} 
+0

我会对此表示赞赏,但我已经使用swap解决了问题,并将成员更改为'currentWeapon'和'storedWeapon'。我认为它正在做我想要的东西,它似乎在工作。 – 2014-11-25 03:03:43

1

在一般情况下,移动后移出对象的对象处于有效但未指定的状态。这意味着您只能安全地调用没有先决条件的移动对象上的那些函数。例如破坏通常没有先决条件。通常也不分配给对象。并且通常既不会const观察者,例如与不移动值的等式比较。

std::unique_ptr的情况下,可以安全地比较移入的值。但也要注意unique_ptr独特的所有权语义。即两个非空unique_ptr s永远不应该相等,因为如果他们这样做,他们会拥有相同的指针,从而违反了unique_ptr的基本租户。但它通常是有意义的比较unique_ptrnullptr找出如果它拥有一个非空指针:

#include <cassert> 
#include <memory> 

int 
main() 
{ 
    std::unique_ptr<int> p(new int(3)); 
    auto p2 = std::move(p); 
    assert(p == nullptr); // perfectly legal & practical use of moved-from value 
} 

我怀疑你的代码的问题是/是你错误地期待从unique_ptr移动复制语义转让:即转让的来源将保持不变。然而,从我上面的代码片段可以看出,移动从unique_ptr将可靠左侧等于nullptr。根本没有其他的方式来执行操作,同时仍然满足所有unique_ptr规格。