C++ 向量元素被最后一次调用push_back替换

C++ Vector elements being replaced by last call to push_back

本文关键字:push back 替换 调用 最后一次 向量 元素 C++      更新时间:2023-10-16

所以我的主函数中有这段代码

if(mesType == 1) {
        cin.ignore();
        Message mes1;
        stack1.push(&mes1);
} else if(mesType == 2) {
        cin.ignore();
        MorseCodeMessage mes2;
        stack1.push(&mes2);
}

这是函数

void MessageStack::push(Message *ms1) {
    messages.push_back(ms1);    
}

消息所在的位置

vector <Message*> messages;

你能解释一下为什么我的消息向量中的所有元素都被我最后推送的任何元素所取代吗?

你正在推送指向局部变量的指针,这很可能会产生未定义的行为;如果局部对象没有超出范围,你有机会重复推送同一对象(局部变量)的地址。请注意,局部变量的内容将更改,并且所有先前推送的地址仍指向同一对象。

您正在推送指向局部变量的指针,这些变量在每次推送后都会超出范围。 堆栈空间会随着时间的推移而重复使用,因此您最终可能会得到指向同一堆栈内存的多个指针,但向量中的指针在技术上是悬而未决的,使用它们是未定义的行为。

由于您显然具有派生自Message的多态类,因此您需要使用 new 动态分配它们,以便它们在存储在向量中时保持活动状态:

if(mesType == 1) {
    cin.ignore();
    Message *mes1 = new Message;
    stack1.push(mes1);
} else if(mesType == 2) {
    cin.ignore();
    MorseCodeMessage *mes2 = new MorseCodeMessage;
    stack1.push(mes2);
}

不要忘记使用虚拟析构函数定义Message,然后在使用完向量或从向量中删除项时对每个指针调用delete。 否则,您将有内存泄漏。

在 C++11 及更高版本中,更安全的解决方案是使用 std::unique_ptr 而不是原始指针:

std::vector<std::unique_ptr<Message>> messages;
void MessageStack::push(std::unique_ptr<Message> ms1) {
    messages.push_back(std::move(ms1));
}
...
if(mesType == 1) {
    cin.ignore();
    stack1.push(std::unique_ptr<Message>(new Message));
    // or, in C++14 and later:
    //stack1.push(std::make_unique<Message>());
} else if(mesType == 2) {
    cin.ignore();
    stack1.push(std::unique_ptr<Message>(new MorseCodeMessage));
    // or, in C++14 and later:
    //stack1.push(std::make_unique<MorseCodeMessage>());
}