Kurze frage zu std::map und POD's



  • Hallo, ich habe eine kruze Frage zu maps und POD's. Eine Methode, die ich schon oft gesehen habe, um zB die Wörter einer Datei zu zählen, sieht so aus:

    std::map<std::string, unsigned int> woerter;
    
    ifstream in("dateiname");
    std::string tmp;
    while(in>>tmp)
        ++woerter[tmp];
    

    Nun frage ich mich, ob beim erstellen eines neuen Elementes in map die Zählvariable automatisch auf 0 gesetzt wird. Denn normalerweise, wenn ein neuer POD wert erzeugt wird, ist er ja nicht 0 (weil es eben keinen "Standardkonstruktor" gibt).
    Garantiert mir der Standard also, dass, wenn ich über den [] Operator ein neues Element zur map hinzufüge, ein POD "mapped value" auf 0 gesetzt wird?



  • mapPod schrieb:

    Garantiert mir der Standard also, dass, wenn ich über den [] Operator ein neues Element zur map hinzufüge, ein POD "mapped value" auf 0 gesetzt wird?

    Ja.

    23.3.1.2 schrieb:

    map element access [lib.map.access]
    T& operator[](const key_type& x);
    Returns: (*((insert(make_pair(x, T()))).first)).second

    Lustige Definition, aber da ist klar ein T() ersichtlich. T ist der zweite Templateparameter, und unsigned int() erzeugt ein null-initialisiertes Objekt.



  • T() bedeutet "value initialization". Wenn T ein POD ist, dann läuft es im Endeffekt aber auf "zero initialization" hinaus.



  • Nexus schrieb:

    23.3.1.2 schrieb:

    map element access [lib.map.access]
    T& operator[](const key_type& x);
    Returns: (*((insert(make_pair(x, T()))).first)).second

    Lustige Definition, aber da ist klar ein T() ersichtlich. T ist der zweite Templateparameter, und unsigned int() erzeugt ein null-initialisiertes Objekt.

    Was soll n das sein? Wenn es den Wert schon gibt, wird doch nicht nochmal initialisiert. Wo steht das?



  • Da: Returns: (*((insert(make_pair(x, T()))).first)).second



  • Ehrlich??? T() bedeutet, dass er nicht nochmal initialisiert wird, wenn es schon so einen Eintrag gibt?



  • Nö. Aber insert gibt in dem Rückgabepair einen Iterator auf ein vorhandenes Element zurück, wenn es schon ein solchen mit dem gleichem Key gibt. Das T() wird in dem Fall also gar nicht beachtet.



  • Das passt doch auch nicht, vor nem Funktionsaufruf müssen doch die Parameter ausgewertet werden.

    class foo{
    	static int m;
    public:
    	int n;
    	foo():n(0)
    	{
    		std::cout<<"riesen aufwand: "<<++m << std::endl;
    	}
    };
    
    int foo::m = 0;
    
    int main()
    {
    	std::map<int,foo> m;
    	foo f;
    	f.n = 66;
    	m[8] = f;
    	m[7] = f;
    	foo g;
    	g.n=99;
    	std::cout<<"n: "<<m[8].n<<std::endl;
    	m[8] = g;
    	std::cout<<"n: "<<m[8].n<<std::endl;
    }
    

    riesen aufwand: 1
    riesen aufwand: 2
    riesen aufwand: 3
    riesen aufwand: 4
    n: 66
    n: 99

    Also bei der VS2008 Implementierung ist ein if drin, was auch sinn macht.

    mapped_type& operator[](const key_type& _Keyval)
    		{	// find element matching _Keyval or insert with default mapped
    		iterator _Where = this->lower_bound(_Keyval);
    		if (_Where == this->end()
    			|| this->comp(_Keyval, this->_Key(_Where._Mynode())))
    			_Where = this->insert(_Where,
    				value_type(_Keyval, mapped_type()));
    		return ((*_Where).second);
    		}
    	};
    

    Aber meine Abneigung gegen map[key] = value ist jetzt noch größer als sie vorher schon war.



  • needed here



  • In dem Draft von 2005 steht das dann (nur noch) leserlich:

    Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.
    

    Vom aktuellen Standard habe ich leider nur einen Working-Draft von 1995 - aber wenn im richtigen auch noch
    Returns: (*((insert(make_pair(x, T()))).first)).second steht, dann ist die MS-Implementation vrmtl. falsch(aber in meinen Augen sinnvoll)...

    bb



  • unskilled schrieb:

    In dem Draft von 2005 steht das dann (nur noch) leserlich:

    Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.
    

    Vom aktuellen Standard habe ich leider nur einen Working-Draft von 1995 - aber wenn im richtigen auch noch
    Returns: (*((insert(make_pair(x, T()))).first)).second steht, dann ist die MS-Implementation vrmtl. falsch(aber in meinen Augen sinnvoll)...

    Ich würde eher sagen der alte Standard ist falsch. 😃


  • Mod


Log in to reply