2013-12-29

C++03とC++11の違い: 文字列ライブラリ編

今日も今日とて、C++03とC++11の違いを解説する。今回は、文字列ライブラリー編だ。

変更: basic_stringをリファレンスカウントで実装することを禁止

C++が設計中の時代は、文字列を保持するストレージを文字列クラスで共有して、参照数を記録しておき、変更された時だけ書き換えるような実装が、主に使われていた。


class String
{
private :
    char * storage ;
    unsigned int * count ;

public :
    String()
        : storage( new char[100] ), count( new unsigned int(0) )
    { }

    // コピー時に共有する
    String( String const & s )
        : storage( s.storage), count( s.count )
    { count++ ; }

    // 誰も所有していなければ解放
    ~String( )
    {
        --count ;
        if ( count == 0 )
        {
            delete count ;
            delete[] storage ;
        }
    } 
} ;

このようなCOWによる文字列クラスの実装は、30年前はともかく、今となってはとても効率が悪い。なぜならば、マルチコア、マルチスレッドが当たり前になってしまったからだ。今は文字列クラスをCOWで実装すべきパフォーマンス上の理由がないので、C++11では、COWで実装することは規格で禁止された。

変更: Small-string optimizationの許可

Small-string optimizationとは、文字列クラスの最適化手法のひとつである。多くの文字列クラスのオブジェクトは、短い文字列を扱うという点に着目して、あらかじめ短い文字列を、クラスオブジェクト自体に格納できるようにしておくのだ。


class String
{
    std::size_t size ;
    char sso[8] ;
    char * storage ;

    String( char const * ptr )
    {
        size = std::strlen( ptr ) ;

        if ( size > 8 )
        { // usual allocation
            storage = new char [ size ] ;
            std::copy_n( ptr, size, storage ) ;
        }
        else
        { // small-string optimization
            std::copy_n( ptr, size, sso ) ;
        }
    }
} ;

このように非常に短い文字列の場合はクラスオブジェクト自体で保持できるようにすれば、短い文字列ならば、動的にストレージを確保せずに保持できる。そして、文字列クラスの利用には、このような短い文字列のりようがとても多い。

small-string optimizationは、最近の文字列ライブラリの一般的な最適化手法になっている。従来の規格では、イテレーターが無効になる条件の都合上、small-string optimizationは、規格上許されていなかった。その制限はC++11で緩和された。

次回は、コンテナーライブラリー編だ。

No comments: