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

从语义上和概念上以及就神圣标准而言,它每次都会被创建。

其余的取决于您的编译器以及您如何支持她:

可能编译器可以内联调用,然后将推导的不变量移到单个初始化点。

可能编译器不喜欢您的函数具有外部链接,因此没有内联它,然后很难从其他函数中看到该不变量。

boost::assign::map_list_of( A, "A" )( B, "B" )( C, "C" ) 当编译器可以查看内部并验证不会改变全局状态时,编译器可能会始终检查变量的常量性并使用一次性初始化。

许多因素,唯一确定的方法是查看生成的代码。


响应报价请求:

3.7.2.3 [basic.std.auto]:

如果命名的自动对象具有初始化或具有副作用的析构函数,则不应在其块结束之前将其销毁,即使看起来未使用,也不应作为优化消除,除非类对象或其副本可以按照“中的规定消除”

这基本上意味着它要么有副作用,在这种情况下它不会被消除,要么它没有,在这种情况下,它在 C++ 中很难观察到;这实际上意味着:

观察到的行为总是好像每次都被调用一样

换句话说:没有办法保证初始化只发生一次自动存储,所以永远不要假设相反

于 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 回答