Можем ли мы полагаться на трюк с уменьшенной емкостью?

Действительно ли это гарантировано в любом случае, что «трюк» с уменьшенной мощностью будет «работать»?

int main() { std::string s = "lololololol"; s = ""; // capacity still non-zero string(s).swap(s); // ? } 

Мне кажется, что он «не работает» для меня (в том, что емкость остается ненулевой), и я не могу найти ничего в стандарте, который говорит что-то большее, чем «содержимое» должно быть заменено между двумя [здесь , идентичные] объекты.

Аналогично, для контейнеров последовательностей:

 int main() { vector v { 1,2,3,4,5 }; v.clear(); // capacity still non-zero vector(v).swap(v); // ? } 

Насколько мне известно, этот «трюк» широко используется; возможно, это широкое принятие ошибочно?

(Конечно, в C ++ 11 вместо этого у меня есть shrink_to_fit [хотя и не обязательный], что делает этот вид спорным.)

Меня всегда учили, что нет гарантированного стандартного способа снизить пропускную способность. Все методы были (и до сих пор) реализованы.

В § 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 , усадка для соответствия и четкость – это разные трюки. Если цель состоит в том, чтобы полностью очистить, можно ожидать, что замена с построенной по умолчанию строкой даст лучшие результаты.

  • Сортировка сжатых (заблокированных) контейнеров в C ++ с использованием boost или STL
  • Можете ли вы удалить элементы из std :: list во время итерации через него?
  • stoi и std :: to_string on mingw 4.7.1
  • Преобразование std :: __ cxx11 :: string в std :: string
  • Как получить сообщение об ошибке при сбое openstream
  • Должен ли я использовать std :: function или указатель функции в C ++?
  • Как реализуется std :: string?
  • Сглаживание iteratorа
  • Передача rvalues ​​через std :: bind
  • Является ли C ++ std :: set streamобезопасным?
  • В чем разница между «STL» и «C ++ Standard Library»?
  • Давайте будем гением компьютера.