我有一个使用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对象,也许切换案例效率更高。第一个问题:我在创造垃圾?
第二个解决方案:
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];
没关系?更好的解决方案?
答案 0 :(得分:4)
第二种解决方案似乎对我好 - 你可以说:
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 )));
答案 1 :(得分:3)
第一种解决方案会产生大量垃圾。你为什么不按价值归还班级?它非常轻巧,你不必动态分配它。
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];
}
如果返回的课程变大,而您想要一个电动工具,请尝试boost::flyweight。
如果您不想传回大型结构,可以执行以下操作:
HistoParameter& variable_to_parameter(char* var_name)
{
// same code
}
...如果你想要它不可变,甚至可以投入const
。
修改:按照Niel的建议添加了make_pair。
答案 2 :(得分:1)
您的第二个解决方案当然应该提高效率,但不是(至少IMO)可能的最佳实施。首先,它使first_time
公开可见,即使只有variable_to_parameter
实际关心它。您已在函数中为hp
设置了静态变量,first_time
也应如此。
其次,我不会对HistoParameter值使用指针和/或动态分配。在一个int和两个浮点数中,根本没有理由这样做。如果你真的传递它们以至于复制成为一个问题,你可能最好使用某种智能指针类而不是原始指针 - 后者更难以使用而且更难以制作例外安全。
第三,我会考虑将variable_to_parameter变为函数而不是函数是否值得。在这种情况下,您将在ctor中初始化地图,因此您不必每次调用operator()
时都检查它是否已初始化。您还可以通过在仿函数中使用静态地图来组合这两者。如果它不存在,则ctor初始化它,operator()只进行查找。
最后,我注意到map::operator[]
主要用于插入项目 - 如果项目不存在则创建具有指定键的项目,但是当您查找项目时,通常不想创建一个项目。为此,您通常最好使用map.find()
。
答案 3 :(得分:0)
我有一个std :: map&lt; std :: string,HistoParameter *&gt;会员并做
InitializeHistoParameter()
{
myMap["ph_pt"] = new ...
myMap["ph_eta"] = new ...
}
然后
HistoParameter* variable_to_parameter(char* var_name)
{
return myMap[var_name];
}
答案 4 :(得分:0)
无论哪种方式,您都在创建内存泄漏。
每次调用=
运算符时,例如:
hp[std::string("ph_pt")] = new HistoParameter(100,0,22000);
您正在创建一个新的HistoParameter对象,并将关键字“ph”与此最新对象配对,让前一个对象悬空。 如果每次创建一个新对象是您的实际意图,您可能需要调用
delete hp[std::string("ph_pt")];
在new
操作之前。
我的建议是尽可能避免原始new
操作,并使用boost::share_ptr等智能指针进行对象生命周期管理。