3

GetName()質問の最後の例を考えると、関数が呼び出されるたびにマップ オブジェクトが作成されますか?
それとも、作成が最適化されてルックアップ テーブルとして作成されるのでしょうか?

#include <iostream>
#include <sstream>
#include <map>
#include <string>
#include <boost/assign/list_of.hpp>

enum abc
{
    A = 1,
    B,
    C
};

std::string GetName( const abc v )
{
    const std::map< abc, std::string > values =
        boost::assign::map_list_of( A, "A" )( B, "B" )( C, "C" );
    std::map< abc, std::string >::const_iterator it = values.find( v );
    if ( values.end() == it )
    {
        std::stringstream ss;
        ss << "invalid value (" << static_cast< int >( v ) << ")";
        return ss.str();
    }
    return it->second;
}

int main()
{
    const abc a = A;
    const abc b = B;
    const abc c = C;
    const abc d = static_cast< abc >( 123 );

    std::cout<<"a="<<GetName(a)<<std::endl;
    std::cout<<"b="<<GetName(b)<<std::endl;
    std::cout<<"c="<<GetName(c)<<std::endl;
    std::cout<<"d="<<GetName(d)<<std::endl;
}
4

2 に答える 2

5

意味的にも概念的にも、聖な​​る基準に関しても、毎回作成されます。

残りはあなたのコンパイラとあなたが彼女をどのようにサポートするか次第です:

おそらく、コンパイラは呼び出しをインライン化し、推定された不変条件を外部の初期化の単一ポイントに移動できます。

おそらく、コンパイラは関数に外部リンケージがあることを嫌い、インライン化しないため、他の関数からその不変式を見つけるのに苦労します。

おそらく、コンパイラは常に変数 constness をチェックし、内部を調べてboost::assign::map_list_of( A, "A" )( B, "B" )( C, "C" ) グローバル状態を変更しないことを確認できる場合は、1 回限りの初期化を使用します。

多くの要因があり、確実に確認する唯一の方法は、生成されたコードを確認することです。


見積もり依頼への対応:

3.7.2.3 [basic.std.auto]:

名前付き自動オブジェクトに初期化または副作用のあるデストラクタがある場合、そのブロックの終了前に破棄されたり、未使用のように見えても最適化として削除されたりしてはなりません。に指定されているように削除される場合があります」

これは基本的に、副作用がある場合は除去されないか、除去されていない場合は C++ 内ではほとんど観察できないことを意味します。これは効果的に次のことを意味します。

観測された動作は、常に毎回呼び出されているかのようです。

つまり、初期化が自動ストレージで 1 回だけ行われることを保証する方法はないため、逆のことを想定しないでください。

于 2011-06-21T09:47:45.570 に答える
0

ファンクターを使用しないのはなぜですか?

#include <iostream>
#include <sstream>
#include <map>
#include <string>
#include <boost/assign/list_of.hpp>


enum abc
{
    A = 1,
    B,
    C
};

class LookupTable
{
    typedef std::map<abc, std::string> map_type;

public:
    LookupTable(const map_type &values)
    : table(values)
    {}

    std::string operator()(abc v) const
    {
         map_type::const_iterator it = table.find(v);
         if (table.end() == it)
         {
             std::stringstream ss;
            ss << "invalid value (" << static_cast< int >( v ) << ")";
            return ss.str();
         }
         return it->second;
    }

private:
    const map_type table;
};


int main()
{
    std::map<abc, std::string> values = boost::assign::map_list_of( A, "A" )( B, "B" )( C, "C" );
    LookupTable GetName(values);

    const abc a = A;
    const abc b = B;
    const abc c = C;
    const abc d = static_cast< abc >( 123 );

    std::cout<<"a="<<GetName(a)<<std::endl;
    std::cout<<"b="<<GetName(b)<<std::endl;
    std::cout<<"c="<<GetName(c)<<std::endl;
    std::cout<<"d="<<GetName(d)<<std::endl;
}
于 2011-06-21T10:36:13.280 に答える