Referenz auf eine std::map ? [gelöst]



  • Hallo,

    bei einer Berechnung möchte ich gerne per Referenz auf eine map zugreifen um gleichzeitig die Werte ändern zu können. Jetzt bin ich mir aber nicht sicher ob ich jedes mal im Speicher eine map anlege und die irgendwie da hängen bleibt.

    Kann ich das wie folgt machen oder Mülle ich damit den Speiche zu?

    void Analysis::calculate(Gradient* curve) const
    {
    	map<string,float>& data = *(new map<string, float>);
    
    	switch(curve->getType())
    	{
    	case 1:
    		data = curve->maxValues;
    		break;
    	case 2:
    		data = curve->minValues;
    		break;
    		//....
    	}
    
    	// Berechnung mit data
    	// ...
    }
    


  • Sharpie schrieb:

    map<string,float>& data = *(new map<string, float>);
    

    Ergibt irgendwie nicht so richtig Sinn. Wenn du keine Referenz hast, dann erstell eben lokal eine neue Map, und nicht wie hier auf dem Heap. Wenn du dann noch vergisst die Map mit delete zu löschen, dann hast du ein schönes Speicherleck.

    map<string,float> data;
    


  • Du legst hier eine Map auf dem Heap an und lässt die Referenz data auf diese verweisen. Das produziert natürlich ein Speicherleck (jedenfalls sehe ich in diesem Codeabschnitt kein delete).

    Dann, im switch-Block, kopierst Du eine Map aus dem curve-Objekt in diese Map, die Du zuvor angelegt hast. Wenn Du später an data Änderungen vornimmst, ändert sich die Map in dem curve-Objekt also nicht.

    Merke: Referenzen können nach ihrer erstmaligen Initialisierungen nicht mehr umgebogen werden! Wenn Du sowas hier machen möchtest, nimm einen Zeiger.



  • Vielen Dank!

    Also eine neue Map würde ich nur ungern erstellen, da ich diese anschließend wieder in das curve-Objekt zurück schreiben muss um die Änderungen zu speichern. In diesem Fall würde mir ein Zeiger auf das curve-Objekt bzw. die Map besser gefallen.

    Wie bekomme ich aber einen entsprechenden Zeiger auf die Map im curve-Objekt?



  • map<string,float> *myMap = &curve->curveMap;
    curve->curveMap = *myMap;
    


  • map<string,float> *myMap = &curve->curveMap;
    curve->curveMap = *myMap;
    

    Danke für das Beispiel, aber ich habe noch ein kleines Verständnis Problem. Für was ist das notwendig:

    curve->curveMap = *myMap;
    

    Ich ändere dann über myMap doch direkt die Werte in curve->curveMap, oder? Zumindest zeigt mir das mein Debugger auch so an!

    Warum kann ich aber nur so über den Key an den Wert kommen:

    myMap[0]["ID"];
    

    und nicht über

    myMap["ID"];
    

    ist das so richtig?



  • Überleg mal, was myMap für ein Typ hat. Es ist keine map! (sondern ein Zeiger auf eine)



  • drakon schrieb:

    Überleg mal, was myMap für ein Typ hat. Es ist keine map! (sondern ein Zeiger auf eine)

    Ja ist mir auch klar, dass myMap ein Zeiger auf eine map ist. Deshalb müsste auch *myMap["ID"] funktionieren oder? Es sollte doch dem entsprechen:

    int *a, b;
    b = 17;
    a = &b;
    

    Dann greife ich doch mit *a auf den Inhalt der Variable zu. Demzufolge sollte doch auch *myMap["ID"] möglich sein oder? Deutet jeder Zeiger dann auf ein Array da ich mit myMap[0]["ID"] zugriff habe und in diesem Fall wäre nur ein Feld belegt?



  • Sharpie schrieb:

    Deshalb müsste auch *myMap["ID"] funktionieren oder?

    Die Idee ist vollkommen korrekt, allerdings bindet der []-Operator stärker als der *-Operator. Somit muss man (*myMap)["ID"] schreiben.



  • Sharpie schrieb:

    Demzufolge sollte doch auch *myMap["ID"] möglich sein oder?

    Nein. Die operator-Rangfolge ist andersrum. Was du da schreibst ist *(myMap["ID"]) und nicht (*myMap)["ID"]

    Sharpie schrieb:

    Deutet jeder Zeiger dann auf ein Array da ich mit myMap[0]["ID"] zugriff habe und in diesem Fall wäre nur ein Feld belegt?

    Bei einem Zeiger bedeutet ptr[n] das selbe wie *(ptr + n) , in deinem Fall also (*myMap)["ID"] - was zufälligerweise das ist was du willst.
    Zufälligerweise deshalb, weil es nicht den Anschein macht als hättest du die Hintergründe verstanden und wüsstest genau warum es so funktioniert wie es funktioniert. Ich rate daher, dich einmal genauer mit Pointersemantik und mit der Operator-Rangfolge zu beschäftigen. (Wenn man sich mit der nicht genau auskennt, ist es nicht so schlimm, nur sollte man dann sicherheitshalber Klammern setzen bevor man Ausdrücke fabriziert die keinen Sinn ergeben)



  • Vielen Dank an alle für die tolle Hilfe. Habe jetzt so weit alles verstanden und für den Rest habe ich ja noch ein paar Bücher 😉


Anmelden zum Antworten