指针的迭代向量导致分段错误

时间:2019-05-24 18:35:30

标签: c++

我是C ++编程的新手。我正在尝试使用指向某些Command实例的指针向量来实现Command设计模式。

我可以使用另一个方法(例如,使用索引访问每个元素)遍历向量,但是我想了解为什么会出现错误。

我假设vector连续分配每个元素,并且每个元素都具有相同的大小。

struct Command {
    virtual void execute(){};
};

struct CommandOne : Command {
    std::string member = "string";
    void execute() override{
        std::cout << member << std::endl;
    }
};

struct CommandTwo : Command {
    void execute() override {
        std::cout << "string" << std::endl;
    }
};

CommandOne commandOne{};
CommandTwo commandTwo{};
std::vector<Command*> commands;

int main (int argc, char** argv){
    commands.push_back(&commandOne);    
    commands.push_back(&commandTwo);    
    Command* ptr_commands = commands.at(0);
    ptr_commands->execute();
    ptr_commands++;
    ptr_commands->execute();
    return 0;
}

预期输出为:

string
string

但是我得到了

string
segment fault

1 个答案:

答案 0 :(得分:4)

出于所有意图和目的,这里的两个struct对象位于内存中的随机位置。从at返回的指针指向其中之一,并且仅其中之一。它们在内存中不一定是连续的。递增该指针不是有效的操作。

处理此问题的最佳方法是使用古老的for循环在向量上进行迭代:

for (auto c = commands.begin(); i != commands.end(); ++i) {
  (*c)->execute();
}

在更新的C ++中,它甚至可能看起来像:

for (auto c : commands) {
  c->execute();
}

您还需要考虑使用新的C ++迭代器功能,例如for_each

for_each(commands.begin(), commands.end(), [](Command* c) { c->execute(); });

您还需要确保在程序终止之前的某个时候,用new分配的任何内容都能正确地用delete释放。通过分配,您将承担清理的责任。别忽略了。

正如alter在下面的评论中指出的那样,unique_ptr是减轻这种责任的好方法。