Что означает этот список отличий в реальном коде? Определите массивы объектов типа char, vector, list и string со значением "Hello", передайте его в функцию в качестве аргумента, напишите количество символов в передаваемой строке, попытайтесь сравнить его со строкой "Hello" в функции (чтобы убедиться, что вы действительно передали строку "Hello"), а затем сравните аргумент со строкой "Howdy", чтобы увидеть, какое из этих слов появляется в словаре первым. Скопируйте аргумент в другую переменную того же типа.
ПОПРОБУЙТЕ
Выполните предыдущее задание ПОПРОБУЙТЕ для массива объектов типа int, vector и list со значениями { 1, 2, 3, 4, 5 } .
20.7.1. Операции insert и erase
insert() и erase()), в векторе происходит перемещение остальных элементов; это может оказаться связано с неприемлемыми затратами, если вектор содержит большое количество элементов или элементы вектора сами являются крупными объектами. Однако слишком беспокоиться об этом не следует. Мы без заметных проблем считали полмиллиона значений с плавающей точкой в вектор, используя функцию push_back(). Измерения подтвердили, что предварительное выделение памяти не приводит к заметным последствиям. Прежде чем вносить значительные изменения, стремясь к эффективности, проведите измерения (угадать степень эффективности кода трудно даже экспертам).
insert(), erase(), and push_back()), не следует хранить итераторы или указатели на элементы вектора. Если элемент будет перемещен, ваш итератор или указатель будет установлен на неправильный элемент или вообще может не ссылаться на элемент вектора. В этом заключается принципиальное преимущество класса list (и класса map; см. раздел 21.6) над классом vector. Если вам необходима коллекция крупных объектов или приходится ссылаться на объекты во многих частях программы, рассмотрите возможность использовать класс list.
Сравним функции insert() и erase() в классах vector и list. Сначала рассмотрим пример, разработанный специально для того, чтобы продемонстрировать принципиальные моменты.
vector
++p; ++p; ++p; // устанавливаем итератор
// на 4-й элемент
vector
++q; // устанавливаем итератор
// на 5-й элемент
p = v.insert(p,99); // итератор p ссылается на вставленный элемент
Теперь итератор q является неправильным. При увеличении размера вектора элементы могли быть перемещены в другое место. Если вектор v имеет запас памяти, то он будет увеличен на том же самом месте, а итератор q скорее всего будет ссылаться на элемент со значением 3, а не на элемент со значением 4, но не следует пытаться извлечь из этого какую-то выгоду.
p = v.erase(p); // итератор p ссылается на элемент,
// следующий за стертым
Иначе говоря, если за функцией insert() следует функция erase(), то содержание вектора не изменится, но итератор q станет некорректным. Однако если между ними мы переместим все элементы вправо от точки вставки, то вполне возможно, что при увеличении размера вектора v все элементы будут размещены в памяти заново.
Для сравнения мы проделали то же самое с объектом класса list:
list
++p; ++p; ++p; // устанавливаем итератор
// на 4-й элемент
list
++q; // устанавливаем итератор
// на 5-й элемент
p = v.insert(p,99); // итератор р ссылается на вставленный элемент
Обратите внимание на то, что итератор q по-прежнему ссылается на элемент, имеющий значение 4.
p = v.erase(p); // итератор р ссылается на элемент, следующий
// за удаленным