Подсчет ссылок std :: string - PullRequest
4 голосов
/ 28 июля 2010

Я смотрю на код для basic_string (в комплекте с g ++ 4.2.1).Конструктор копирования использует функцию grab(), чтобы «захватить» копию строки (увеличить ее счетчик ссылок):

_CharT* _M_grab( const _Alloc& __alloc1, const _Alloc& __alloc2 ) {
  return (!_M_is_leaked() && __alloc1 == __alloc2) ? _M_refcopy() : _M_clone(__alloc1);
}

Это увеличивает счетчик ссылок только в том случае, если распределители для двухСтроки одинаковы - имеет смысл.Тем не менее, конструктор копирования:

basic_string(const basic_string& __str)
: _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()), __str.get_allocator()),
              __str.get_allocator())
{ }

Первый распределитель, который передается _M_grab(), является копией второго.Зачем?Единственный способ, которым operator==() для allocator может вернуть false, - это если пользователь использует собственный распределитель.Однако, даже если это правда, вы бы подумали, что скопированный распределитель будет сравниваться равным его оригиналу, верно?Итак:

  1. Зачем вообще сравнивать распределители?
  2. Зачем копировать-создавать распределитель и сравнивать копию с оригиналом?
  3. Какой пример использования при сравнениикопия с оригиналом вернула бы ложь?

Обновление

Да, _M_grab() используется в другом месте: для присвоения.В этом случае распределители, переданные в _M_grab() , отличаются .Хорошо.Но, похоже, нет оснований для копирования-конструирования, а затем для сравнения распределителей в конструкторе для string.

Ответы [ 2 ]

1 голос
/ 28 июля 2010
  1. Распределители сравниваются равными, если объекты, выделенные из одного, могут быть освобождены с другим.Если это так, то две строки могут совместно использовать ссылку на один и тот же распределитель;в противном случае каждому нужен свой собственный распределитель.

  2. Сравнение происходит внутри _M_grab, который не знает, что один аргумент был сконструирован из другого аргумента в данном конкретном случае._M_grab также вызывается из assign, где две строки могут иметь разные распределители.

  3. Распределитель всегда должен сравниваться равным копии самого себя.

Обновление

Но, похоже, нет оснований копировать-конструировать, а затем сравнивать распределители в конструкторе для строки.

Также нет особой причины для реализации двух почти идентичных версий _M_grab(), чтобы избежать ненужного сравнения, которое (для большинства распределителей) произойдет во время компиляции в любом случае.Может быть, вы думаете, что такая микрооптимизация была бы желательной;по-видимому, автор этого кода не сделал.

1 голос
/ 28 июля 2010

Я знаю zip о рассуждениях команды GCC, но вот мои предположения:

  1. Для отладки?Распределители ДОЛЖНЫ быть одинаковыми.

  2. Так что он может повторно использовать _M_grab ()?

  3. Никогда не должно случиться?1015 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...