Информация об изменениях

Сообщение Re[3]: COW устарел, осторожнее с его использованием? от 24.08.2022 1:31

Изменено 24.08.2022 4:49 Андрей Тарасевич

Re[3]: COW устарел, осторожнее с его использованием?
Здравствуйте, pax123, Вы писали:

P>Здравствуйте, Андрей Тарасевич, Вы писали:


P>>>В чем проблема с COW?


АТ>>Проблема с COW не имеет никакого отношения к многопоточности. Проблема с COW заключается в том, что данные в `std::string` официально являются непрерывным массивом и спецификация `std::string` разрешает бесконтрольную раздачу итераторов/указателей/ссылок на этот массив. Это запросто может приводить к возникновению "висящих" итераторов/указателей/ссылок в таком многообразии однопоточных контекстов, что пытаться специфицировать правила инвалидации таких итераторов/указателей/ссылок — бесперспективное занятие.


P>Не понятно, чем в этом случае строка с COW отличается от строки без этого


Один из заезженных примеров, которые приводят в таком случае — это вызов оператора `[]`. Стандарт хочет, чтобы вызов `[]` даже для неконстантного объекта, сам по себе не приводил к расщеплению, т.е. к COPY. В частности, вот в таком примере

std::string a = "abc";
const char *ptr = a.data();

{
  std::string b = a;
  a[0];
}

// ...


после вызова `a[0]` происходит расщеплению и объект `b` оказывается единственным владельцем исходных данных. Уничтожение `b` в конце блока приводит к тому, что после завершения блока `ptr` оказывается висящим указателем.

В С++03 пытались выдумывать какие-то более сложные правила, призванные объяснить пользователю, что "так делать нельзя". Но потом к С++11 просто плюнули и постулировали, что такой код не имеет права инвалидировать `ptr`. В спецификации `std::string` появилось простое и прямое требование 23.4.3.2/4.2

> 4 References, pointers, and iterators referring to the elements of a basic_­string sequence may be invalidated by the following uses of that basic_­string object:

> (4.1) Passing as an argument to any standard library function taking a reference to non-const basic_­string as an argument.212
> (4.2) Calling non-const member functions, except operator[], at, data, front, back, begin, rbegin, end, and rend.

Вот это "except..." и поставило крест на COW.
Re[3]: COW устарел, осторожнее с его использованием?
Здравствуйте, pax123, Вы писали:

P>Здравствуйте, Андрей Тарасевич, Вы писали:


P>>>В чем проблема с COW?


АТ>>Проблема с COW не имеет никакого отношения к многопоточности. Проблема с COW заключается в том, что данные в `std::string` официально являются непрерывным массивом и спецификация `std::string` разрешает бесконтрольную раздачу итераторов/указателей/ссылок на этот массив. Это запросто может приводить к возникновению "висящих" итераторов/указателей/ссылок в таком многообразии однопоточных контекстов, что пытаться специфицировать правила инвалидации таких итераторов/указателей/ссылок — бесперспективное занятие.


P>Не понятно, чем в этом случае строка с COW отличается от строки без этого


Один из заезженных примеров, которые приводят в таком случае — это вызов оператора `[]`. Стандарт хочет, чтобы вызов `[]` даже для неконстантного объекта, сам по себе не приводил к расщеплению, т.е. к COPY. В частности, вот в таком примере

std::string a = "abc";
const char *ptr = a.data();

{
  std::string b = a;
  a[0];
}

// ...


для полноценной работы COW после вызова `a[0]` должно происходить расщепление, в результате которого объект `b` окажется единственным владельцем исходных данных. Уничтожение `b` в конце блока приведет к тому, что после завершения блока `ptr` окажется висящим указателем.

В С++03 пытались выдумывать какие-то более-менее сложные правила, призванные объяснить пользователю, что "так делать нельзя". Но потом к С++11 просто плюнули и постулировали, что такой код не имеет права инвалидировать `ptr`. В спецификации `std::string` появилось простое и прямое требование 23.4.3.2/4.2

> 4 References, pointers, and iterators referring to the elements of a basic_­string sequence may be invalidated by the following uses of that basic_­string object:

> (4.1) Passing as an argument to any standard library function taking a reference to non-const basic_­string as an argument.212
> (4.2) Calling non-const member functions, except operator[], at, data, front, back, begin, rbegin, end, and rend.

Вот это "except..." и поставило крест на COW.