2014-09-20 2 views
-1

EDIT: C++ STL set update is tedious: I can't change an element in place не отвечает на мой вопрос.Доступ к множеству элементов разрушительно

Тип данных map позволяет получать доступ к своим элементам посредством ссылок. Это позволяет нам изменять их разрушительно. Из описания, похоже, это также должно быть возможно с типом данных set. Однако для наборов их итераторы возвращают копий элементов в наборе вместо ссылок. Не следует ли возвращать итератору ссылку?

Минимальный рабочий пример:

struct Test { 
    const int id_; 

    explicit Test(const int id) 
    : id_(id) {} 

    bool operator==(const Test & other) const { 
    return id_ == other.id_; 
    } 
    bool operator<(const Test & other) const { 
    return id_ < other.id_; 
    } 
}; 

int main() { 
    std::set<Test> tests; 

    tests.insert(Test(10)); 
    tests.insert(Test(20)); 

    Test & test = *tests.find(Test(10)); 

    return 0; 
} 

На что НКУ 4.9.1 ответов:

test.cpp: In function 'int main()': 
test.cpp:26:37: error: invalid initialization of reference of type 'Test&' from expression of type 'const Test' 
    Test & test = *tests.find(Test(10)); 

Таким образом, на самом деле, есть две проблемы:

  1. Набор итератора возвращает копии вместо ссылок.
  2. Итератор множества всегда является константным итератором.

Глядя на исходный код СТЛ GCC, я наткнулся на:

// _GLIBCXX_RESOLVE_LIB_DEFECTS 
// DR 103. set::iterator is required to be modifiable, 
// but this allows modification of keys. 
typedef typename _Rep_type::const_iterator iterator; 
typedef typename _Rep_type::const_iterator const_iterator; 

который подтверждает выпуск 2 и приводит меня к мысли, что есть на самом деле проблема с этим СТЛ реализации.

+1

В чем вопрос? – juanchopanza

+0

Почему * итератор возвращает копию вместо ссылки. –

+0

Лучше спросите этот вопрос * в вопросе *, а не в комментариях. – juanchopanza

ответ

2

Посмотрите на http://en.cppreference.com/w/cpp/container/set.

В нем четко указано, что поскольку C++ 11, std::set знает только постоянные итераторы, возможно, чтобы вы случайно не изменяли, где должен быть вставлен элемент.

И в любом случае, тип возврата const T&, а не const T.

Это означает, что вы можете изменить элемент на месте, если вы убедитесь, что компилятор знает, что вы делаете, путем кастинга, но если это изменит порядок сортировки, вы получите то, что заслуживаете.

+0

Он должен быть '' 'const T &' '', но является '' 'const T''' с glibcxx, как и состояния выхода компилятора. –

+1

@ joca.bt: Не удается подтвердить, что итератор является '_Rb_tree_iterator ', чей оператор разыменования имеет ссылку на возвращаемый тип. (Таким образом, 'const element &') – Deduplicator

+0

Спасибо. Я также смотрю на код, и он точно определяет это '' 'reference operator *() const'''. Меня смущает выход gcc. –

Смежные вопросы