Frage

Ich mache ein Spiel mit SDL, das libconfig verwendet, um einige Einstellungen aus einer Datei zu lesen.Das Problem ist, dass ich eine Klasse namens erstellt habe ClipList das enthält a std::vector<SDL_Rect> um die Einstellungen zu speichern, aber beim Versuch, sie hinzuzufügen SDL_Rect Objekte auf den Vektor, aus irgendeinem Grund tut push_back nichts und am Ende habe ich einen leeren Vektor.

Das ist die Klasse:

class ClipList
{
    public:
        ClipList();
        ClipList(int);
        virtual ~ClipList();
        void addClip(int,int,int,int);
        void getClip(int,SDL_Rect*);
        int getLength();
    protected:
    private:
    std::vector<SDL_Rect> clips;
};
ClipList::ClipList(int l)
{
    clips.reserve(l);
}

void ClipList::addClip(int x,int y,int w,int h){
    SDL_Rect rect;
    rect.x = x;
    rect.y = y;
    rect.w = w;
    rect.h = h;
    clips.push_back(rect);
}

void ClipList::getClip(int i,SDL_Rect* rect){
rect = &(clips.at(i));
}

int ClipList::getLength(){
    return clips.size();
}

Und das ist die Funktion, mit der ich das ClipList-Objekt initialisiere.Diese Funktion wird von main aufgerufen.

void set_clips(Config* placlips,ClipList* clips, ClipList* flipclips){
    const Setting& root = placlips->getRoot();
    int x,y,w,h;
    try{
        Setting& clipsett = root["clips"];
        int cliplen = clipsett.getLength();
        clips = new ClipList(cliplen);
        flipclips = new ClipList(cliplen);
        for(int i=0;i<cliplen;i++){
            const Setting& c = clipsett[i];
            if(!(c.lookupValue("x",x)&&c.lookupValue("y",y)&&c.lookupValue("w",w)&&c.lookupValue("h",h))){
                continue;
            }
            clips->addClip(x,y,w,h);
        }
    }catch(const SettingNotFoundException &nfex){
        cerr << "Setting not found at" << nfex.getPath() << endl;
    }
}

Unabhängig davon, ob die ClipList Objekte werden in initialisiert main oder set_clips, clips.push_back(rect) funktioniert nicht.Die Kapazität des Vektors ändert sich, aber es wird kein Objekt gespeichert. Daher erhalte ich einen Segfault, wenn ich versuche, etwas anderes mit dem Vektor zu tun, auch wenn ich überprüfe, ob der Vektor leer ist oder nicht.

War es hilfreich?

Lösung

Ich werde raten, die Signatur der Funktion

void set_clips(Config* placlips,ClipList* clips, ClipList* flipclips);

ist der Schuldige.Sie reservieren Speicher für clips Und flipclips in dieser Funktion, aber da die Zeiger als Wert übergeben werden, sieht die aufrufende Funktion den zugewiesenen Speicher nicht.

Wenn Sie die Funktionssignatur ändern in:

void set_clips(Config* placlips, ClipList*& clips, ClipList*& flipclips);

Deine Probleme sollten verschwinden.

Andere Tipps

clips.push_back(rect) funktioniert gut.Dein set_clips Die Funktion weist neue ClipList-Instanzen zu, gibt diese Zeiger jedoch nicht an den Aufrufer zurück.Der Aufrufer versucht wahrscheinlich, einen Müllzeiger als Initialisierungsinstanz zu verwenden, und deshalb erhalten Sie einen Segfault.

Sie müssen die erstellten Objekte zurückgeben.Sie sollten dazu etwas wie std::shared_ptr<> anstelle von bloßen Zeigern verwenden.

Update zur Vorgehensweise ohne Verwendung von std::shared_ptr<>:

Sie müssen den Überblick über die Eigentumsverhältnisse behalten und mit Ausnahmen umgehen.In Bezug auf die tatsächliche Übergabe lautet die von mir verwendete Regel (ursprünglich von Lakos in „Large Scale C++ Software Design“), dass Parameter, die Rückgabewerte sind (so wie Sie sie zu verwenden versuchen), Zeiger sind und schreibgeschützte Parameter by Wert oder Konstantenreferenz.Rückgabewerte stehen an erster Stelle.

Also dein set_clips Funktion sollte so aussehen:

void set_clips(ClipList** clips, ClipList** flip_clips, Config const& placlips)

Wenn du anrufst set_clips Sie übergeben einen Zeiger an jeden Zeiger, der den zugewiesenen Wert empfängt, und übergeben eine konstante Referenz an das Placlips-Objekt, das von der Funktion nicht geändert wird.

Sie würden das Ganze etwa so gestalten:

ClipList* clips = 0;
ClipList* flip_clips = 0;
set_clips(&clips, &flip_flips, placlips);
// ... then do whatever comes next.

Aber die Kombination dieser Regeln mit std::shared_ptr<> oder boost::shared_ptr<> ist besser und der „moderne C++“-Stil.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top