2010-07-28 2 views
4

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

_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. Что такое прецедент, когда сравнение копии с ее оригиналом вернет false?

Update

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

+1

Я не могу видеть остальную часть кода здесь, но возможно ли реальная утилита для того, когда '_M_grab()' вызывается из другого места, и здесь дополнительная копия распределителя выполняется только для см., является ли распределитель как способным к копированию, так и сопоставлением копий? Очевидно, что если первое не соответствует действительности, вызов даже не будет компилироваться, но если последнее неверно, управление ресурсами будет вести себя корректно. – seh

+0

@seh: Ваш «последний» случай имеет какой-то смысл, но я не могу придумать прецедента, где копировально-распределенный распределитель не сравнится с его оригиналом - кажется очень странным. Однако, по-видимому, это не так уж редко, потому что авторы этого класса строк рассматривали это. Поэтому мне любопытно, что может быть в этом случае. –

ответ

1

Я знаю молнию о рассуждении команды НКИ, но вот мои предположения:

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

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

  3. Никогда не должно произойти?

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

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

  3. Распределитель должен всегда сравнивать его с копией.

Update

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

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

+0

Если # 3 всегда верно, то зачем документировать его? Почему бы просто не передать __str.get_allocator() для обоих аргументов в _M_grab()? –

+1

@Paul: Вы правы; похоже, что явная копия не нужна, но безвредна. 'get_allocator()' возвращает копию в любом случае. –

+0

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

Смежные вопросы