2016-07-22 19 views
0

Я немного перепутался с const_iterators. Например, давайте рассмотрим функцию:Почему компилятор позволяет отправлять ссылку на итератор в функции, которая принимает ссылку на const iterator?

void functionForConstIterator(std::list<int> const& list, std::list<int>::const_iterator& const_iter) 
{ 
    const_iter = list.begin(); 
} 

Теперь можно написать:

void main() 
{ 
    std::list<int> myList = {1, 2, 3, 4, 5}; 
    std::list<int> const& listRef = myList; 
    std::list<int>::iterator iter; 

    functionForConstIterator(listRef, iter); 
    *iter = 7; 

    for (auto it = myList.begin(); it != myList.end(); ++it) 
     std::cout << *it << " "; 
} 

Выход {7, 2, 3, 4, 5}. Зачем? Если я получаю ссылку на константу в контейнере, я не должен ее менять. Это компилятор Visual Studio 2015.

+0

Если параметр функции является константной ссылки, что просто означает, что функция не может изменить его. Это не заставит его начинать быть const вне функции. – JETM

+0

[Ваш код фиктивный] (http://coliru.stacked-crooked.com/a/1bc62e737a7e80f4) –

+0

Но это означает, что если у меня есть ссылка только const, а не сам контейнер, я всегда могу ее изменить. –

ответ

1

Microsoft STL's list::iterator происходит от list::const_iterator. Вот почему вы можете передать ссылку на ваш iterator на функцию, ожидающую const_iterator без проблем.

Таким образом, назначение внутри функции является назначением среза, но это не имеет особого эффекта в этом случае, поскольку iterator не имеет виртуальных функций и не вводит новых членов.

Таким образом, у вас есть незавершенное преобразование const_iterator в iterator благодаря заданию.

Edit: Я создал вопрос Connect для этого:

https://connect.microsoft.com/VisualStudio/feedback/details/2962643

+0

Является ли такая реализация запрещена стандартом? –

+0

Я не думаю, что это технически, поскольку стандарт указывает, что «это может не компилироваться» только в очень немногих местах библиотеки, но это, безусловно, очень плохое качество реализации. –

2

Если я получаю ссылку на константу на контейнере, я не могу ее изменить.

Это верно. Однако вы не получаете ссылку на константу в контейнере. несмотря на его название, const_iterator является не a const с точки зрения языка. Имя const должно указывать программистам, что вы не сможете изменить контейнер через этот итератор. Итератор сам по себе остается справедливой целью, которую нужно изменить.

Кроме того, итератор является const_iterator только внутри функции. Вне функции, то есть в main, это обычный std::list<int>::iterator, который остается полностью изменчивым до и после вызова функции.

+0

Но это следует за тем, что если у меня есть ссылка только const, а не сам контейнер, я всегда могу изменить контейнер. Что такое ссылки на const в этом случае? –

+0

Реальный вопрос: следует ли вам прямо или косвенно назначить константный итератор неконстантному итератору и тем самым изменить базовый контейнер.И ответ, ИМО, должен быть ** нет **. – nonsensickle

+0

Чтобы прояснить мое утверждение далее, изменение 'const_iterator' на прямой' iterator' не должно допускаться для выполнения неявно или косвенно. – nonsensickle

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

  • Нет связанных вопросов^_^