题
我有一个使用 std::map 转换数据的函数
struct HistoParameter
{
int nbins;
float first;
float last;
HistoParameter(int _nbins, int _first, int _last) :
nbins(_nbins), first(_first), last(_last) {};
};
HistoParameter* variable_to_parameter(char* var_name)
{
std::map<const std::string, HistoParameter*> hp;
hp[std::string("ph_pt")] = new HistoParameter(100,0,22000);
hp[std::string("ph_eta")] = new HistoParameter(100,-3,3);
// ...
return hp[var_name];
}
我的结构很轻,但想象它可能很重。问题是,每次我调用这个函数时,它都会创建很多 HistoParameter 对象,也许 switch case 更有效。第一个问题:我在制造垃圾吗?
第二种解决方案:
bool first_time = true;
HistoParameter* variable_to_parameter(char* var_name)
{
static std::map<const std::string, HistoParameter*> hp;
if (first_time)
{
hp[std::string("ph_pt")] = new HistoParameter(100,0,22000);
hp[std::string("ph_eta")] = new HistoParameter(100,-3,3);
// ...
}
first_time = false;
return hp[var_name];
可以吗?更好的解决方案?
解决方案
您第二溶液当然应该提高效率,但不是(至少IMO)的最佳实施的可能。首先,它使first_time
公开可见,尽管实际上只variable_to_parameter
它的忧虑。你已经做hp
在函数中的静态变量,first_time
应该也是如此。
其次,我不会用指针和/或动态分配用于HistoParameter值。在一个int和两个浮体,也根本没有理由这样做。如果你真的路过他们身边这么多,复制就成了问题,你可能会被关闭使用某种智能指针类而不是原始指针的更好 - 后者是使用更困难,更难以做出异常安全。
第三,我会考虑它是否值得做variable_to_parameter成仿函数,而不是一个功能。在这种情况下,你会初始化地图的构造函数,这样你就不必检查它是否每operator()
被调用时初始化。您也可以将二者结合起来,通过在函子静态地图。所述构造函数初始化它,如果它不存在,和操作员()只是做一个查找。
最后,我想指出,map::operator[]
是将项目主要是有用的 - 它具有指定键创建一个项目,如果它不存在,但是当你正在寻找一个项目,你通常不希望创建一个项目。对于这一点,你通常最好是关闭使用map.find()
代替。
其他提示
第二个解决方案似乎确定我 - 你可以说:
if ( hp.empty() ) {
// populate map
}
我也考虑将其映射一个值,而不是指针 - 我不知道你在这里需要动态分配:
std::map <std::string, HistoParameter> hp;
然后:
hp["ph_pt"] = HistoParameter(100,0,22000);
请注意,你不需要明确的std :: string转换。或者更好的是:
hp.insert( std::make_pair( "ph_pt", HistoParameter(100,0,22000 )));
在第一溶液中产生大量的垃圾。你为什么不按值返回类?这是相当轻巧,你wouln't必须动态地分配它。
HistoParameter variable_to_parameter(char* var_name)
{
static std::map<const std::string, HistoParameter> hp;
if ( hp.empty() )
{
hp.insert( std::make_pair( "ph_pt", HistoParameter(100,0,22000) ) );
hp.insert( std::make_pair( "ph_eta", HistoParameter(100,-3,3) ) );
//...
}
return hp[var_name];
}
如果返回的类变大,你想一个电源工具,然后尝试的升压::轻量级。
如果您不想传回一个大的结构,你可以这样做:
HistoParameter& variable_to_parameter(char* var_name)
{
// same code
}
...甚至在const
如果你想让它一成不变的抛出。
修改:强>加入make_pair,如由尼尔建议
我不得不一个std ::地图<的std :: string,HistoParameter *>构件和做
InitializeHistoParameter()
{
myMap["ph_pt"] = new ...
myMap["ph_eta"] = new ...
}
然后
HistoParameter* variable_to_parameter(char* var_name)
{
return myMap[var_name];
}
不管怎样,你都会造成内存泄漏。每次 =
调用运算符,例如:
hp[std::string("ph_pt")] = new HistoParameter(100,0,22000);
您正在创建一个新的 HistoParameter 对象,并将键“ph”与这个最新的对象配对,而前一个对象则悬空。如果每次创建一个新对象是您的实际意图,您可能需要调用
delete hp[std::string("ph_pt")];
之前 new
手术。
我的建议是避免生食 new
尽可能多地进行操作并诉诸智能指针,例如 升压::share_ptr 用于对象生命周期管理。