我有一个使用 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 用于对象生命周期管理。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top