2014-11-25 125 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規格。