2013-03-29 10 views
8

Wiem, że to straszny pomysł, aby zmienić klucz obiektu w zbiorczym pojemniku, ale zastanawiam się, gdzie dokładnie zabrania mi tego standard. Rozważmy:Dlaczego nie zmodyfikować klucza pojemnika asocjacyjnego?

#include <map> 
#include <memory> 

struct X { int i; }; 

struct lt 
{ 
    bool operator()(const std::shared_ptr<X>& lhs, 
        const std::shared_ptr<X>& rhs) const 
    { 
    return lhs->i < rhs->i; 
    } 
}; 

int main() 
{ 
    std::map< std::shared_ptr<X>, int, lt > m; 
    auto x = std::make_shared<X>(); 
    x->i = 1; 
    m.insert(std::make_pair(x, 2)); 

    x->i = 42; // change key wrt the container! 
} 

Zakładam, że powyższe powinny być nielegalne, ale czytałem standard od jakiegoś czasu i nie mogę znaleźć niczego, co rzeczywiście sprawiato nielegalne. Gdzie to jest? A może ukrywa się w przyszłym raporcie o usterkach?

+0

std :: map ma strukturę wewnętrzną drzewa. Jeśli zmodyfikujesz klucz, struktura wewnętrzna nie jest poprawna i wyszukiwanie nie zadziała, ponieważ pójdziesz na złą ścieżkę. – Felics

+0

@Felics: To nie było pytanie. –

+0

W "Skutecznym STL" S. Meyersa znajduje się cały rozdział poświęcony właśnie temu zagadnieniu (patrz punkt 22). Zabawne jest to, że dość trudno jest zniszczyć wewnętrzną strukturę mapy (ponieważ typem mapy jest "para ") - musisz użyć do tego jakiegoś aliasingu - to jest ** bardzo ** łatwe do rozbicia zestaw i multiset, ponieważ możesz przypisać do '* it', gdy' it' jest zbiorem (multi) :: iteratorem. – shakurov

Odpowiedz

9

Wprowadza niezdefiniowane zachowanie w programie, jeśli modyfikuje się wartości w taki sposób, że porównanie dwóch kluczy różni się po zmianie zgodnie z określonym komparatorem.

z pkt 23.2.4/3 C++ 11 standardowych associative.reqmts ([]):

Wyrażenie „Równoważność klawiszy” oznacza stosunek równoważności nałożone porównania i nie operator== na klucze. Oznacza to, że dwa klucze k1 i k2 są uważane za równoważne, jeżeli dla porównaniaobiekt , comp(k1, k2) == false && comp(k2, k1) == false. Dla każdego z dwóch kluczy k1 i k2 w tym samym pojemniku, wywołanie comp(k1, k2) zawsze zwraca tę samą wartość.

+0

Ups. Nie widziałem tego. : D – Nawaz

+1

+1 i zaakceptowany, ale dlaczego podświetlone zdanie nie jest jego własnym punktem wypunktowania, a zamiast tego jest pochowane za i w kontekście "równoważności kluczy"? Dziwne. –

+5

@DanielFrey: Nie wiem, ale wydaje mi się, że cały Standard ma tendencję do grzebania odpowiednich zdań gdzieś, gdzie są one trudne do wykrycia;) –

Powiązane problemy