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 に答える