c++ - 为什么 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++ 的容器中存储引用(不是指针)不起作用?
问题的前提是正确的。您不能将引用存储在容器中。
...它编译得很好。
不能安全地假定不导致编译器错误的代码是正确的。实际上,“编译时没有错误”是您可以对代码设置的最低标准。考虑一下这个非常糟糕的代码:
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
在容器中存储引用。
推荐阅读
- websphere - 如何在 IBM HTTP Server 上启用 SSLv3?
- xquery - 如何检查我的 cts:and-query 或 cts:or-query 是否包含任何元素查询
- python - 为什么这个队列在多处理中不起作用?(函数体中的 append() 方法)
- javascript - 无法从 Node.js 修改 HTML 元素的值
- autodesk-forge - 关于锻造的第一人称
- javascript - 反应原生时刻格式的日期无效
- django - 反序列化与属性名称不同的字段名称
- ios - AppStore 为我的 ios 应用程序拒绝此消息的原因是什么?
- c# - 在 Visual Studio 中组织 EF 配置类的最佳实践
- python - 检查列表中的任何值是否存在于句子中