C++交换UNQUICHYPTR

C++交换UNQUICHYPTR,c++,smart-pointers,unique-ptr,C++,Smart Pointers,Unique Ptr,对这类事情不熟悉,可能做错了什么,但是- 我有3名成员 std::unique_ptr<Gun> currentWeapon; std::unique_ptr<Gun> weaponSlotOne; std::unique_ptr<Gun> weaponSlotTwo; 我有一个切换武器的方法,它可以: void Player::switchWeapons() { if(currentWeapon == weaponSlotOne) {

对这类事情不熟悉,可能做错了什么,但是-

我有3名成员

std::unique_ptr<Gun> currentWeapon;
std::unique_ptr<Gun> weaponSlotOne;
std::unique_ptr<Gun> weaponSlotTwo;
我有一个切换武器的方法,它可以:

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

由于某种原因,它似乎摧毁/释放了两支枪。我不太确定出了什么问题。

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

在您的情况下,在执行currentwarel=std::movewearponslotone;,之后;,武器音调是不确定的,所以当您测试Current武器==武器音调时,您可能会得到任何结果。很可能,这将是错误的武器音调将为空,所以您只需将其复制到Current武器,删除其中的任何内容即可

问题是,你想做什么?如果你想要两种武器,并且想知道哪一种是最新的,那么做可能更有意义:

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;
}

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

在您的情况下,在执行currentwarel=std::movewearponslotone;,之后;,武器音调是不确定的,所以当您测试Current武器==武器音调时,您可能会得到任何结果。很可能,这将是错误的武器音调将为空,所以您只需将其复制到Current武器,删除其中的任何内容即可

问题是,你想做什么?如果你想要两种武器,并且想知道哪一种是最新的,那么做可能更有意义:

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;
}

通常,从对象移动后,从对象移动的对象处于有效但未指定的状态。这意味着您只能安全地在moved from对象上调用那些没有先决条件的函数。例如,销毁通常没有先决条件。通常情况下,分配给对象也不会。通常情况下,const观察器(如与非moved-from值的相等比较)也不会这样做

对于std::unique_ptr,您可以安全地比较moved from值。但还要注意,unique_ptr具有唯一的所有权语义。也就是说,两个非空的unique_ptr永远不应该比较相等,因为如果它们比较相等,它们将拥有相同的指针,因此违反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 move赋值中获得复制语义:即赋值的源将保持不变。然而,从我上面的代码片段可以看出,moved from unique_ptr将可靠地保持等于nullptr。在仍然满足所有唯一的ptr规范的情况下,没有其他方法实现该操作。

通常,从对象移动后,从对象移动的对象处于有效但未指定的状态。这意味着您只能安全地在moved from对象上调用那些没有先决条件的函数。例如,销毁通常没有先决条件。通常情况下,分配给对象也不会。通常情况下,const观察器(如与非moved-from值的相等比较)也不会这样做

对于std::unique_ptr,您可以安全地比较moved from值。但还要注意,unique_ptr具有唯一的所有权语义。也就是说,两个非空的unique_ptr永远不应该比较相等,因为如果它们比较相等,它们将拥有相同的指针,因此违反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 move赋值中获得复制语义:即赋值的源将保持不变。然而,从我上面的代码片段可以看出,moved from unique_ptr将可靠地保持等于nullptr。在满足所有独特的ptr规范的同时,根本没有其他方法来实现该操作。

以防有人登上这篇文章。您可以在共享指针或唯一指针上使用std::swap

编辑: 尽量避免使用以下代码:

weaponSlotOne.reset(new DevPistol());
它可能导致内存泄漏。最好是:

weaponSlotOne = std::make_unique<DevPistol>();

以防有人登上这篇文章。您可以在共享指针或唯一指针上使用std::swap

编辑: 尽量避免使用以下代码:

weaponSlotOne.reset(new DevPistol());
它可能导致内存泄漏。最好是:

weaponSlotOne = std::make_unique<DevPistol>();

unique_ptr在这种情况下没有意义也许:?unique_ptr在这种情况下没有意义也许:?我会对此进行投票,但我已经通过使用swap解决了这个问题,并将成员更改为CurrentWearm和storedWeapon。我想它正在做我希望它做的事情,它似乎在工作。我将对此进行投票,但我已经通过使用交换和更改成员来解决它 现在的武器和储存的武器。我想它正在做我想做的,它似乎在工作。