是std::映射表初始化优化
Is std::map table initialization optimized?
考虑到问题末尾的示例,是否每次调用函数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;
}
从语义和概念上以及就神圣标准而言,它每次都会被创建。
剩下的取决于你的编译器以及你如何支持她:
编译器可能会内联调用,然后将推导出的不变量移到外部到单个初始化点。
编译器可能不喜欢函数有外部链接,所以不内联它,所以很难从其他函数中看到这个不变量。
编译器可能总是检查变量常量并使用一次性初始化当它可以查看内部并验证boost::assign::map_list_of( A, "A" )( B, "B" )( C, "C" )
不会改变全局状态。
许多因素,唯一可以确定的方法是查看生成的代码。
响应报价请求:
3.7.2.3[基本.std.auto]:
如果一个命名的自动对象有初始化或有副作用的析构函数,则在其块结束前不得将其销毁,也不得将其作为优化消除,即使它看起来未使用,除非类对象或其副本可以按照"
这基本上意味着,要么它有副作用,在这种情况下它不会被消除,要么它没有,在那种情况下它在C++中很难观察到;这意味着有效地:
观察到的行为总是,就好像每次都调用它一样
换句话说:无法保证初始化只在自动存储中发生一次,因此永远不要假设相反的情况。
为什么不使用函子?
#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;
}
相关文章:
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 如何让MSVC编译器优化多步POD初始化?
- 具有必要副作用的静态初始化被优化掉了
- GCC缺少优化CTOR初始化器列表的机会
- 数组初始化优化
- 如何使用C++的字节码优化初始化嵌入式 Python 解释器
- 初始化的奇怪优化
- 优化地图上的初始化:转发密钥
- 为什么未初始化容器的行为与优化不同
- 使c++编译器优化到在map初始化时只调用构造函数一次
- 静态初始化器在库中会被优化掉
- 何时允许编译器优化auto+大括号样式的初始化
- 是std::映射表初始化优化