C ++为什么在向量段错误中放置对象?

问题描述 投票:1回答:1

我想创建一个“Act”对象的向量,其中包含指向“Eat”或“Drink”动态分配对象的指针。新对象被放置如下:

action_vector.emplace_back(Act::BehaviorType::eat);

然而,这是分段错误,我无法弄清楚为什么。我认为emplace_back会隐式调用移动构造函数,而不是析构函数,但出于某种原因,它(我认为)是什么阻碍了一切。

有没有办法成功创建这样的对象的向量?

以下是代码的其余部分及其输出。对不起,如果它有点冗长,但基本上它只是一种策略模式。

#include <iostream>
#include <vector>

class IBehavior
{
public:
    IBehavior() = default;
    virtual ~IBehavior() = default;
    virtual void execute() = 0;
};

class Drink : public IBehavior
{
public:
    Drink(): IBehavior() {}
    ~Drink() {}
    void execute() { std::cout << "Drinking" << std::endl; }
};

class Eat : public IBehavior
{
public:
    Eat(): IBehavior() {}
    ~Eat() {}
    void execute() { std::cout << "Eating" << std::endl; }
};


class Act
{
    IBehavior * b;

public:

    enum class BehaviorType { eat = 0, drink = 1 };

    Act() = default;
    ~Act()
    {
        std::cout << "Calling the destructor" << std::endl;
        delete b;
    }
    Act(BehaviorType b_type) { SetBehavior(b_type); }

    Act(Act&& act)
    {
        std::cout << "Calling the move constructor" << std::endl;
        this->b = act.b;
    }


    void SetBehavior(BehaviorType b_type)
    {
        if(b_type == BehaviorType::eat) b = new Eat();
        if(b_type == BehaviorType::drink) b = new Drink();
    }

    void execute() { b->execute(); }
};


int main(int argc, char * argv[])
{
    std::vector<Act> action_vector;

    for(int i = 0; i < 10; ++i)
    {
        action_vector.emplace_back(Act::BehaviorType::eat);
        action_vector[i].execute();
    }

    return 0;
}

输出:

Eating
Calling the move constructor
Calling the destructor
Eating
Calling the move constructor
Calling the move constructor
Calling the destructor
Calling the destructor
Segmentation fault: 11
c++ pointers vector strategy-pattern
1个回答
4
投票

你的移动构造函数复制b,析构函数删除b,所以如果你移动构造一个实例,那么相同的指针值将被删除两次,具有未定义的行为。

一般解决方案:使用智能指针。


另一个错误:默认构造函数使b未初始化。销毁默认构造对象时,将删除未初始化的指针,并且未定义行为。智能指针也可以解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.