2010-09-25

std::initializer_listはどのように実装されるのか

初期化リストを使うにあたって、初心者が信じてしまうかもしれないと懸念される問題は、std::initializer_listは、通常の配列に比べて、遅いのではないかという迷信だ。規格によれば、std::initializer_listは、通常の配列をautomatic storage、もしくはstatic storage上に構築し、その配列へのポインターを格納するのと、何ら変わることはない。

例えば、以下のようなコードは、

void f() 
{
    for ( auto i : { 1, 2, 3 } )
    {
        std::cout << i << std::endl ; 
    }
}

最終的に、以下のように置き換えることができる。

void f()
{
    int a[3] = { 1, 2, 3 } ;
    int * iter = a ;
    int * last = a + 3 ;
    for ( ; iter != last ; ++iter )
    {
        auto i = *iter ;
        std::cout << i << std::endl ;
    }
}

もちろん、細部をどのように実装するかについては、実装により異なる。しかし、初期化リストの各要素を格納するオブジェクトは、automatic storageかstatic storage上に構築可能である。

これを考えれば、std::minとstd::maxを、initializer_listで実装するか、Variadic Templatesで実装するかというのは、パフォーマンスを考えて見れば、ささいな違いではないかと思う。

したがって、std::initializer_listのパフォーマンスを心配するのは、「static変数やローカル変数、関数の実引数や戻り値のオブジェクトは、実装によってどこかよく分からないストレージ上に構築されるので信用ならん」と言うのに等しい。

いや、メモリーじゃなくてストレージという言葉が出てくる時点で、こう考えることはあり得ないか。

No comments: