为什么const容器可以保存const引用?

时间:2020-02-26 20:38:08

标签: c++ reference static containers constants

正如图块所暗示的,在C ++中,由于容器内部的对象必须是可分配的,因此不能包含用于保存引用的引用。引用初始化后,我们无法重新分配它。

但是,在我的程序中,我有一个static const std::map,它将const引用保存为值,并且可以很好地编译。我想知道是不是因为映射被声明为const并在声明时初始化,所以告诉编译器“此对象是const,其内容不会更改,因此可以将const引用作为其值保留”。

我在其他任何地方都找不到答案。该代码有效,但我不想让其他开发人员感到困惑。

编辑, 抱歉,我没有包含代码。在这里:

const glm::dvec4& GetObjectColor(const msg::ObjectType type) {
  static const std::map<msg::ObjectType, const glm::dvec4&> kObjectColorMap = {
      {msg::ObjectType::PERSON, kWhite},
      {msg::ObjectType::ANIMAL, kSilver},
      {msg::ObjectType::SEDAN, kGray},
      {msg::ObjectType::SUV, kRed},
      {msg::ObjectType::VAN, kMaroon},
      {msg::ObjectType::BICYCLE, kYellow},
      {msg::ObjectType::TRICYCLE, kOlive},
      {msg::ObjectType::MOTORCYCLE, kLime},
      {msg::ObjectType::TRUCK, kGreen},
      {msg::ObjectType::BUS, kAqua},
      {msg::ObjectType::PICKUP, kTeal},
      {msg::ObjectType::UNKNOWN, kBlue}};
  return kObjectColorMap.at(type);  
}

1 个答案:

答案 0 :(得分:0)

不。你不能。

也许您已经看到了以下问题:Why does storing references (not pointers) in containers in C++ not work?

问题的前提是正确的。您不能将引用存储在容器中。

...并且可以正常编译。

不能引起编译器错误的代码不能安全地假定为正确。实际上,“编译没有错误”是您可以放到代码上的最低标准。请考虑以下可怕的代码:

int* dont_do_this_at_home;   
*dont_do_this_at_home = 42;   // serisouly: DONT DO THIS

我知道没有编译器会对此代码发出错误或警告,无论该代码无法再被破坏。此处可能发生的最好情况是您遇到了细分错误。最糟糕的是:恶魔从你的鼻子里飞出来。在此处阅读有关未定义行为的信息:https://en.cppreference.com/w/cpp/language/ub

如以上链接的问答中所述,语言规范说:您不能在容器中存储引用。如果仍然这样做,并且编译器不会产生错误,那么您不应假定您找到了解决规则的方法。

这类似于不允许在足球比赛中用手触摸球。您可以用手触摸球,但这并不违反规则。

考虑一下:

int a = 5;
std::map<int,int&> x{ { 1,a} };   // WRONG !!!

没有编译器错误,但仍然是错误的。 C ++不是足球,如果您违反规则,那么没有裁判会告诉您。

PS:有std::reference_wrapper可以将引用存储在容器中。