对这种东西很新,可能做错了什么,但是 -
我有3名成员
std::unique_ptr<Gun> currentWeapon;
std::unique_ptr<Gun> weaponSlotOne;
std::unique_ptr<Gun> weaponSlotTwo;
Gun是一个基类,有其他派生类,如Pistol
和SMG
。
我正在做的是将weaponSlotOne
和weaponSlotTwo
设置为两个不同的枪支,然后将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);
}
}
由于某种原因,它似乎会破坏/解除分配两种枪支。我不太确定出了什么问题。
答案 0 :(得分: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;
}
答案 1 :(得分:1)
通常,在从对象移动后,移动的对象处于有效但未指定的状态。这意味着您只能在没有前提条件的移动对象上安全地调用这些函数。例如,破坏通常没有先决条件。通常也没有分配给对象。并且通常情况下,const观察者都没有例如与非移动值进行相等比较。
对于std::unique_ptr
,您可以安全地比较移动值。但另请注意,unique_ptr
具有唯一所有权语义。即两个非null unique_ptr
s永远不应该相等,因为如果它们相同,它们将拥有相同的指针,因此违反了unique_ptr
的基本租户。但是将unique_ptr
与nullptr
进行比较以确定它是否拥有非空指针通常是有意义的:
#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
规范的情况下,没有其他方法可以实现该操作。
答案 2 :(得分:0)
以防万一有人登上此职位。您可以在共享或唯一指针上使用std :: swap。
http://www.cplusplus.com/reference/memory/shared_ptr/swap/
编辑:
尽量避免这样的代码:
weaponSlotOne.reset(new DevPistol());
它可能导致内存泄漏。更好的是:
weaponSlotOne = std::make_unique<DevPistol>();