提问者:小点点

从地图中获取价值的最佳实践是什么?


我对函数返回有点困惑,我的目的是尽量避免复制。

我读了一些文档,告诉我不要使用reference作为map的值。

但在下面的代码中,我感到困惑。

struct BigCls {
  // this struct has a expensive constructor
  BigCls(...);
};

// solution 1
void create_function() {
  std::map<int, BigCls> m;
  m[1] = BigCls(...);
  m[2] = BigCls(...);
  ...
}

BigCls get(int a) {
  return m.at(a);
}

// solution 2
void create_function() {
  std::map<int, BigCls*> m;
  m[1] = new BigCls(...);
  m[2] = new BigCls(...);
  ...
}

BigCls* get(int a) {
  return m.at(a);
}

// solution 3
void create_function() {
  std::map<int, BigCls&> m;  // i think if map's value is reference, then the cls should be static
  // or it will fail, am i right?
  static BigCls cls(...);
  m[1] = cls;
  ...
}    
BigCls& get(int a) {
  return m.at(a);
}

哪一个最快?你认为哪一个是最好的?


共2个答案

匿名用户

std::map::at

t&at(常量键和键);(1)(自C++11)
常量t&at(常量键和键)常量;(2)(自C++11)

返回对key与key等效的元素的映射值的引用。如果不存在这样的元素,则抛出std::out_of_range类型的异常。

(cppreference)

std::map::at返回元素引用,因此不存在复制行为(除非您将其返回值赋给非引用变量)。

问题中的代码有问题,m变量不应该在函数内部。

除了这个问题之外,将解决方案1中的get函数的返回类型从bigcls更改为bigcls&将是最好的解决方案。

struct BigCls {
  BigCls(...);

  int v1, v2;
};


std::map<int, BigCls> m;

void create_function() {
  m[1] = BigCls(...);
  m[2] = BigCls(...);
  ...
}

BigCls& get(int a) {
  return m.at(a);
}

void examples()
{
  int v1 = get(1).v1;

  BigCls &bigCls2 = get(2);
  int v2 = bigCls2.v2;
}

匿名用户

您不需要在映射中存储引用就可以获得对映射中值的引用。这里:

std::map<int,BigCls> m;

BigCls& get(int a) {
  return m.at(a);
}

您正在返回对映射中值的引用。如果你这样称呼它,就不会复制:

BigCls& x = get(42);

在映射中存储指针是不必要的复杂,除非您实际需要该级别的间接(例如当bigcls是多态类型时)。

哪一个最快?你认为哪一个是最好的?

这听起来像是过早的优化。根据需要副本还是引用,选择返回副本或引用。它意味着函数的不同语义。担心性能是因为您有正确的代码,并且通过分析和测量,您发现它需要改进。