3

I have a vector of object pointers

    std::vector<Element*> elements;

When iterating through the vector, I would like to double dereference the iterator in order to call the object's methods.

    std::cout << (*it)->getName() << std::endl;

This leads to a segfault. The relevant code is below.

I am thinking that the problem is with how I am initializing the vector, because I could move the for-loop to be in the method initialize() and it works fine. In takeTurn(), the vector is of the appropriate size and the pointers contain the correct addresses. Does this mean that the objects being pointed to are being prematurely destroyed?

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;
}
4

4 回答 4

5

您在此处将指向局部变量的指针传递给向量:

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));
于 2013-06-09T14:23:00.650 回答
5

您的初始化功能已损坏。您创建本地对象,然后将它们的地址推送到向量上。但是当函数返回时,这些对象被销毁,指针不再有效。除非您需要多态性,否则最简单的解决方法是只制作一个 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已完成的每个指针。我不推荐这条路线。

于 2013-06-09T14:23:54.473 回答
1

您将悬空指针推入向量:

void initialize() {
    Element ice = Element("ice",1);
    Element fire = Element("fire",2);
    elements.push_back(&ice); 
    elements.push_back(&fire);
}

这里的冰和火是局部变量。您将地址推送到向量,然后在达到最终 } 时都被销毁。稍后当您重新引用此无效指针行为时未定义。

于 2013-06-09T14:22:50.403 回答
1

您的向量存储指向在堆栈上创建的局部变量的指针。函数执行完毕后,这些变量占用的内存将被回收。如果你试图访问内存,你会得到一个段错误。

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;
}
于 2013-06-09T14:25:15.790 回答