我是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
答案 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
是减轻这种责任的好方法。