РЕДАКТИРОВАТЬ : Технически стандарт не требует, чтобы это было правильно, если содержащийся тип имеет конструктор копирования без бросков. Я не знаю ни одной реализации, где это все равно не выполняется, так как это потребовало бы создания двух реализаций push_back
, когда универсальная одинаково эффективна во всех случаях.
Псевдоним - это проблема в целом, но не в этом конкретном случае. Код:
assert( v.size() > 0 );
v.push_back( v[0] );
Гарантируется, что стандарт корректен (C ++ 03) через гарантии исключений (которые являются действительно веской причиной не реализовывать свои собственные контейнеры, вы, вероятно, не получите их правильно). В частности, §23.1 [lib.container.requirements] / 10 диктатов:
Если не указано иное (см. 23.2.1.3 и 23.2.4.3) [ ПРИМЕЧАНИЕ: обе эти ссылки относятся к insert
на deque
и vector
соответственно ] всех типов контейнеров, определенных в этом пункте соответствовать следующим дополнительным требованиям:
- если исключение выдается функцией push_back () или push_front (), эта функция не имеет никаких эффектов .
Если важным битом является то, что если в операции выдается любое исключение, контейнер остается нетронутым , и это означает, что ни один итератор не будет признан недействительным, что, в свою очередь, означает, что исходная область памяти остается нетронутой до тех пор, пока не будет гарантировано, что не будет выброшено никаких исключений (за исключением исключение каламбура деструкторов). Поскольку в общем случае конструкторы копирования могут throw, реализация должна обеспечить выполнение всех копий перед уничтожением любого объекта.
Это становится более очевидным в C ++ 0x, когда объекты не копируются из одного места в другое, а перемещаются . Поскольку копия нового элемента может быть сгенерирована, она должна быть выполнена до того, как будет выполнен любой из ходов, иначе вы останетесь в ситуации, когда некоторые объекты в исходном контейнере были признаны недействительными .