首页 > 解决方案 > 为什么 const 容器可以保存 const 引用?

问题描述

正如图块所暗示的,在 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);  
}

标签: c++referencestaticcontainersconstants

解决方案


你不能。

也许你已经看到了这个问题:为什么在 C++ 的容器中存储引用(不是指针)不起作用?

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

...它编译得很好。

不能安全地假定不导致编译器错误的代码是正确的。实际上,“编译时没有错误”是您可以对代码设置的最低标准。考虑一下这个非常糟糕的代码:

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在容器中存储引用。


推荐阅读