【问题标题】:initialize a member unique_ptr to empty将成员 unique_ptr 初始化为空
【发布时间】:2015-02-28 03:39:05
【问题描述】:

在我的程序中,我有一堆自定义类位置的对象。 Position的声明如下:

class Position {
public:
    Position(int x, int y);
    ~Position();

    Actor *getActor()           { return actor.get(); };
    void setActor(Actor *actor) { actor = std::move(actor); };
    Actor *clearActor()         { return actor.release(); };

    int getX()  { return x; };
    int getY()  { return y; };

private:
    int x, y;
    std::unique_ptr<Actor> actor;
};

我还有一个名为 Actor 的类。不是每个位置都会有一个 Actor,因此大多数时候位置对象的 unique_ptr “actor”应该是空的(我使用 unique_ptrs 在运行时自动清理与位置关联的任何 Actor)。

Position构造函数如下:

Position::Position(int x, int y)
{
    this->x = x;
    this->y = y;
    actor.reset(nullptr);
}

但是,我知道这没有正确地将存储的指针设置为 nullptr,因为当我尝试在 Position::getActor() 中调用 actor.get() 时,我收到如下错误:

____.exe 中 0x01096486 处的第一次机会异常:0xC0000005:访问冲突读取位置 0x00000008。

有没有办法将成员 unique_ptr 初始化为 nullptr?我知道我可以通过向 Actor 类添加一个变量来解决这个问题,该变量定义 Actor 是否处于活动状态,将 unique_ptr 设置为新的非活动 Actor,并忽略所有非活动 Actor,但如果可能的话,我宁愿避免这种情况。

谢谢!

编辑:我添加了调用 getActor 的代码:

bool Grid::addActor(Actor *actor, int x, int y)
{
    Position *destination = at(x, y);

    if (!destination->getActor()) {
        destination->setActor(actor);
        actor->setPosition(x, y);
        actor->setGrid(this);
        return true;
    }
    else {
        inactive_actors.emplace_back(actor);
        return false;
    }
}

【问题讨论】:

  • 你要取消引用getActor()吗?
  • 您的意思是使用位置指针调用它吗?是的。我有一个 Position *pos,我正在检查 pos->getActor() 的值。
  • @PreacherJayne 如果getActor() 返回nullptr,这是未定义的行为。
  • @PreacherJayne 您是否取消引用 getActor 返回的nullptr

标签: c++11 unique-ptr


【解决方案1】:

你的错误在这里:

void setActor(Actor *actor) { actor = std::move(actor); };

您将std::move 的结果分配给参数 actor。您可能打算使用参数actor reset 成员变量actor

void setActor(Actor *actor) { this->actor.reset(actor); };

附带说明,您可以简单地将构造函数更改为:

Position::Position(int x, int y)
: x(x), y(y)
{
}

这将使用参数初始化成员 xy,并将 std::unique_ptr&lt;Actor&gt; actor 默认初始化为 null。

【讨论】:

  • 我将 setActor 更改为 this-&gt;actor.reset(actor) 但仍然遇到异常。另外,我是否需要更改标题中的构造函数声明以匹配该格式?我从来没有使用过初始化列表;我只用 C++ 编程了几个月。
  • 太棒了!我正要提它。
  • @PreacherJayne 构造函数初始化列表是构造函数定义的一部分,就像主体一样,所以不需要放在构造函数声明中。
  • 我将构造函数更改为初始化列表,但在尝试调用 getActor() 时仍然出现异常。
  • @PreacherJayne 当然你可以使用它。您只是不允许取消引用它。例如。 if (!destination-&gt;getActor()),在这里,每当getActor 返回一个时,您就使用nullptr 来检查目标位置是否存在演员。
【解决方案2】:

您不需要将 std::unique 指针初始化为空。只需将其保留为构造函数中的默认空值,并且只将其重置为指向非空指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 2011-07-14
    相关资源
    最近更新 更多