4

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);
}

これは、2 つの文字列のアロケーターが同じ場合にのみ参照カウントをインクリメントします。これは理にかなっています。ただし、コピー コンストラクターは次のとおりです。

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()は、2 番目のアロケータのコピーです。なんで?operator==()forallocatorが false を返す唯一の方法は、ユーザーがカスタム アロケーターを使用している場合です。しかし、それが本当だとしても、コピーされたアロケータは元のアロケータと同じになると思いますよね? そう:

  1. なぜアロケーターを比較するのですか?
  2. アロケータをコピー構築し、コピーをオリジナルと比較するのはなぜですか?
  3. コピーをオリジナルと比較すると false が返されるユースケースは何ですか?

アップデート

はい、_M_grab()別の場所で使用されます: 割り当て用です。この場合、渡されるアロケーター_M_grab() 異なります。罰金。しかし、コピー構築してからコンストラクターのアロケーターを比較する理由はまだないようですstring

4

2 に答える 2

1

私はGCCチームの推論についてzipを知っていますが、ここに私の推測があります:

  1. デバッグ用?アロケーターは同じでなければなりません。

  2. _M_grab() を再利用できますか?

  3. 絶対にあってはならない?

于 2010-07-28T16:14:30.313 に答える
1
  1. 一方から割り当てられたオブジェクトを他方で解放できる場合、アロケーターは同等です。その場合、2 つの文字列が同じアロケータへの参照を共有できます。それ以外の場合は、それぞれに独自のアロケーターが必要です。

  2. この_M_grab特定のケースでは、一方の引数が他方の引数からコピー構築されたことを知りません。_M_grabは from からも呼び出されassign、2 つの文字列が異なるアロケータを持つ場合があります。

  3. アロケーターは、常にそれ自体のコピーと等しい必要があります。

アップデート

しかし、文字列のコンストラクターでコピー構築してからアロケーターを比較する理由はまだないようです。

_M_grab()いずれにせよ、(ほとんどのアロケーターにとって) コンパイル時に発生する不必要な比較を避けるために、2 つのほぼ同一のバージョンの を実装する特に正当な理由はありません。このようなマイクロ最適化が望ましいと思うかもしれません。明らかに、このコードの作成者はそうではありませんでした。

于 2010-07-28T16:27:20.350 に答える