Можем ли мы полагаться на трюк с уменьшенной емкостью?
Действительно ли это гарантировано в любом случае, что «трюк» с уменьшенной мощностью будет «работать»?
int main() { std::string s = "lololololol"; s = ""; // capacity still non-zero string(s).swap(s); // ? }
Мне кажется, что он «не работает» для меня (в том, что емкость остается ненулевой), и я не могу найти ничего в стандарте, который говорит что-то большее, чем «содержимое» должно быть заменено между двумя [здесь , идентичные] объекты.
Аналогично, для контейнеров последовательностей:
- C читать файл по строкам
- Std :: map, которые отслеживают порядок вставки?
- Как удалить элементы из контейнеров STL?
- std :: shared_ptr безопасность streamов
- мне нужно закрыть std :: fstream?
int main() { vector v { 1,2,3,4,5 }; v.clear(); // capacity still non-zero vector(v).swap(v); // ? }
Насколько мне известно, этот «трюк» широко используется; возможно, это широкое принятие ошибочно?
(Конечно, в C ++ 11 вместо этого у меня есть shrink_to_fit
[хотя и не обязательный], что делает этот вид спорным.)
- Как преобразовать std :: chrono :: time_point в строку datetime календаря с дробными секундами?
- Сортировка std :: map с использованием значения
- Какой самый быстрый способ изменить ключ элемента внутри std :: map
- Почему деструктор будущего возвращается из блокировки std :: async?
- Как найти / найти и заменить в стандартной строке?
- Когда необходимо использовать флаг -stdlib = libstdc ++?
- std :: bind перегрузка
- std :: пара ссылок
Меня всегда учили, что нет гарантированного стандартного способа снизить пропускную способность. Все методы были (и до сих пор) реализованы.
В § 23.2.1 \ 8 говорится:
Выражение
a.swap(b)
для контейнеровa
иb
стандартного типа контейнера, отличного отarray
, должно обменивать значенияa
иb
не вызывая никаких операций перемещения, копирования или свопинга для отдельных элементов контейнера …
Это гарантирует, что внутренние указатели векторов должны быть заменены.
Однако я не могу найти ничего, что гарантировало бы способность вновь созданного вектора.
В § 21.4.2 \ 1 говорится, что одним из basic_string
конструктора basic_string
умолчанию является то, что capacity()
возвращает неопределенное значение.
В § 21.4.2 \ 3 говорится, что одним из условий сообщения конструктора экземпляра basic_string является то, что capacity()
возвращает значение, по крайней мере такое же большое, как size()
.
В § 21.4.6.8 \ 2 говорится, что string::swap
выполняется в постоянное время, что (эффективно) требует, чтобы внутренние указатели были заменены.
Насколько я могу судить, соответствующая реализация может иметь string::max_size() { return 4;}
, и поэтому замена всех внутренних элементов из одного буфера на другой будет постоянным. (вектор не может этого сделать)
Очевидно, возьмите все это с солью. Я цитирую из проекта C ++ с Feb28, ’11, и я не могу найти спецификации для конструктора копии вектора. Кроме того, не найти доказательств, это не то же самое, что найти доказательства против .
Скот Мейерс отмечает, что на странице его ошибок для «Эффективного STL» отмечается:
Когда в строковых реализациях используется подсчет ссылок, трюк подкачки с использованием конструктора копирования не уменьшает емкость, поскольку конструктор копирования не выделяет никакой памяти; это просто корректировка счетчика ссылок. Более надежный способ выполнения shrink-to-fit – создать временную строку через конструктор диапазона, например string (s.begin (), s.end ()). Swap (s); Эта версия трюка подкачки более безопасна для векторов, так как она исключает вероятность того, что конструктор копирования скопирует избыточную емкость другого вектора (какие реализации разрешено делать).
Что касается «гарантии», Майерс отмечает:
Языковая полиция требует, чтобы я сообщил вам, что нет гарантии, что этот метод действительно устранит избыточную емкость. Исполнители могут свободно переносить векторы и строки, если хотят, а иногда и хотят. [Эффективный STL, п. 17]
С http://www.gotw.ca/gotw/054.htm :
Некоторые варианты реализации могут немного увеличить емкость до следующего большего размера «размера блока», в результате чего емкость фактически немного превышает размер.
Как это работает, вероятно, полностью определяется реализацией. В отличие от контейнеров, таких как вектор, строки могут иметь очень разные реализации.
Если в реализации строки используется небольшая оптимизация строк, вы не можете снизить пропускную способность за определенный порог. Если в реализации строки используется copy-on-write, то запись не выполняется, и никакой реальной копии не производится.
Согласно http://www.gotw.ca/gotw/054.htm , усадка для соответствия и четкость – это разные трюки. Если цель состоит в том, чтобы полностью очистить, можно ожидать, что замена с построенной по умолчанию строкой даст лучшие результаты.