[英]Segfault when dereferencing iterator for vector of pointers
我有一個對象指針向量
std::vector<Element*> elements;
在迭代向量時,我想重新引用迭代器以調用對象的方法。
std::cout << (*it)->getName() << std::endl;
這導致了段錯誤。 相關代碼如下。
我認為問題在於我如何初始化向量,因為我可以將for循環移動到方法initialize()
並且它工作正常。 在takeTurn()
,向量具有適當的大小,指針包含正確的地址。 這是否意味着被指向的對象過早被破壞?
main.cpp中:
#include <vector>
#include <iostream>
#include "Element.h"
std::vector<Element*> elements;
void initialize() {
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
}
void takeTurn() {
std::vector<Element*>::iterator it;
for(it = elements.begin(); it != elements.end(); ++it) {
std::cout << (*it)->getName() << std::endl;
}
}
int main() {
initialize();
takeTurn();
return 0;
}
element.h展開:
#include <string>
class Element {
public:
Element(std::string name, int id);
int getID() { return id_; }
std::string getName() { return name_; }
private:
int id_;
std::string name_;
};
Element.cpp:
#include "Element.h"
Element::Element(std::string name, int id) {
name_ = name;
id_ = id;
}
您將指向局部變量的指針傳遞給向量:
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
當你退出這個函數時, ice
和fire
不再存在,所以你留下了懸空指針。
這個問題的解決方案取決於你是否真的需要一個指針向量。 使用std::vector<Element>
可能更簡單:
std::vector<Element> elements;
然后
elements.push_back(Element("ice",1));
elements.push_back(Element("fire",2));
您的初始化功能已損壞。 您創建本地對象,然后將其地址推送到向量。 但是當函數返回時,這些對象被銷毀,指針不再有效。 除非您需要多態性,否則最簡單的修復方法是僅生成Element對象的向量,而不是指針。
std::vector<Element> elements;
...
elements.push_back(Element("ice",1));
elements.push_back(Element("fire",2));
如果您需要多態,那么使用智能指針。
std::vector<std::unique_ptr<Element>> elements;
...
elements.push_back(std::unique_ptr<Element>(new Element("ice",1)));
elements.push_back(std::unique_ptr<Element>(new Element("fire",2)));
如果你繼續使用原始指針,那么你需要一些方法來確保對象的持久性,可能是通過用new
分配它們。 然后,您需要確保在使用它們的每個指針上調用delete
。 我不推薦這條路線。
你將懸空指針推入你的矢量:
void initialize() {
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
}
冰與火是局部變量。 你將地址推送到向量,然后當達到最終}時,兩者都被破壞。 稍后重新引用時,此無效指針行為未定義。
您的向量存儲指向堆棧上創建的局部變量的指針。 函數完成后,將回收這些變量占用的內存。 如果您嘗試訪問內存,則會出現段錯誤。
void initialize() {
Element ice = Element("ice",1); // Local variable.
Element fire = Element("fire",2); // Local variable.
elements.push_back(&ice);
elements.push_back(&fire);
} // Ice and fire disappear.
為堆上的元素分配內存:
void initialize() {
Element *ice = new Element("ice",1);
Element *fire = new Element("fire",2);
elements.push_back(ice);
elements.push_back(fire);
}
記得在完成后釋放內存!
typedef std::vector<Element *>::iterator EIter;
for (EIter it = elements.begin(); it != elements.end(); ++it) {
delete *it;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.