Все ли контейнеры STL возвращают свои элементы по ссылке? - PullRequest
7 голосов
/ 18 августа 2011

В эти дни я изучаю STL, и мне было интересно, возвращаются ли контейнеры STL по ссылке ?

например:

vector.first();
map[key];
*vector.begin();
Or any possible return that ends with element (or value type) of container

например:

std::vector<int> elements;
elements.push_back(20);
elements[0]=60; // this will also change the value
elements.front() = 23; // even the functions also behave same way like subscript operator

это относится ко всем контейнерам? или есть какие-то моменты, которые я не учел?

Ответы [ 4 ]

13 голосов
/ 18 августа 2011

Возврат добавленного элемента или контейнера в функциях-членах контейнера безопасным способом невозможен. Контейнеры STL в основном обеспечивают «сильную гарантию» . Возврат манипулируемого элемента или контейнера сделает невозможным предоставление сильной гарантии (это обеспечит только «базовую гарантию»). Объяснение этих условий приведено на веб-сайте Boost по адресу Исключительная безопасность в общих компонентах . См. Ниже с сайта Boost .

  • Базовая гарантия : что инварианты компонента сохраняются и ресурсы не просачиваются.
  • надежная гарантия : что операция либо успешно завершена, либо вызвала исключение, оставляя состояние программы точно таким, каким оно было до начала операции.
  • гарантия отсутствия бросков : операция не вызовет исключение.

Вернуться к теме: Согласно этому предыдущему SO-ответу , причина этого в том, что возвращение чего-либо может вызвать конструктор копирования, который может вызвать исключение. Но функция уже вышла, поэтому она успешно выполнила свою основную задачу, но все же вызвала исключение, которое является нарушением строгой гарантии. Вы можете подумать: «Ну, тогда давайте вернемся по ссылке!» , хотя это звучит как хорошее решение, но и не совсем безопасно. Рассмотрим следующий пример:

MyClass bar = myvector.push_back(functionReturningMyClass()); // imagine push_back returns MyClass&

Тем не менее, если оператор присвоения копии генерирует ошибку, мы не знаем, был ли push_back успешным или нет, тем самым косвенно нарушая строгую гарантию. Хотя это не прямое нарушение. Конечно, использование MyClass& bar = //... вместо этого решило бы эту проблему, но было бы весьма неудобно, чтобы контейнер мог войти в неопределенное состояние только потому, что кто-то забыл &.

Довольно похожая причина лежит в том, что std::stack::pop() не возвращает выбранное значение. Вместо этого top() возвращает самое верхнее значение безопасным способом. после вызова top, даже когда выдает конструктор копирования или конструктор присвоения копии, вы все равно знаете, что стек не изменился.

2 голосов
/ 18 августа 2011

Да, перегруженный оператор [] для контейнеров stl возвращает ссылку. Так что в приведенных выше примерах значения в m и elements будут изменены.

С http://www.cplusplus.com/reference/stl/vector/operator%5B%5D/:

Определение или оператор [] для вектора:

reference operator[] ( size_type n );
const_reference operator[] ( size_type n ) const;

Где 'Типы элементов reference и const_reference являются ссылочными типами для элементов векторного контейнера (обычно определяемые как T& и const T& соответственно в большинстве моделей выделения памяти).

Редактировать: Помните, что не все контейнеры stl имеют перегруженный оператор []. Те, которые не являются: list, multimap, multiset, priority_queue, queue, set и stack.

2 голосов
/ 18 августа 2011

Все типы контейнеров (последовательность, ассоциативные) предназначены для обеспечения согласованного интерфейса (где это возможно).Это делает их изучение относительно легким, а их использование - еще проще (при условии, что вы выучили их правильно!в случае ассоциированных контейнеров он будет создан первым).Для контейнеров последовательности это поднимает интересный вопрос о проверке границ - но это другая история.Точно так же, если вы предпримете любую другую обычную операцию (insert и т. Д.), У вас будет аналогичный интерфейс.Ваш любимый справочник, как правило, предоставит всю необходимую информацию.

1 голос
/ 13 сентября 2011

std::vector<bool> разрешено возвращать что-то кроме ссылки на bool (при условии, что вы действительно имеете в виду стандартную библиотеку, а не SGI STL). Но это также обычно рассматривается как ошибка, которая не заслуживает того, чтобы называться контейнером.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...