为什么我可以修改const按引用返回?

时间:2018-11-01 14:29:20

标签: c++

考虑以下代码:

std::unordered_map<std::string, std::string> test;
test.insert(std::unordered_map<std::string, std::string>::value_type("test", "123"));
std::string& x = test.at("test");
x += "hi";
std::cout << x << ", " << test.at("test") << std::endl;

此代码按预期方式显示“ 123hi,123hi”。

这是违反直觉的,因为unordered_map::at返回一个const引用: https://en.cppreference.com/w/cpp/container/unordered_map/at

因此,如果我引用了unordered_map::at的返回值,那我就不能修改其内容,对吗?还是我完全误解了const return的含义?据我了解,该代码甚至不应该编译。

现在,如果将std::string&更改为std::string,我将看到复制构造函数按预期执行。该程序将打印123hi, 123,表明映射中包含的值未修改。

这里有两个问题:

  1. 为什么我可以修改const引用?
  2. 如果我要使用字符串x来执行移动操作,例如std::move(x)(引用string& x的原始声明),则移动将按预期进行,或者最终完成会因为const引用而变成副本构造函数?

2 个答案:

答案 0 :(得分:14)

  

unordered_map::at返回const引用

不,不是。它有两个重载:一个const,一个没有。您正在使用非常量重载。

答案 1 :(得分:7)

std::unordered_set::at有两个重载,一个重载为const限定的实例,一个重载为非const限定的实例。一个重载确实返回了a。不可修改的const参考。试试这个:

const

此示例显示const std::unordered_map<std::string, std::string> test = {{"test", "123"}}; // ^^ Note the const-specifier std::string& x = test.at("test"); // No way, compiler will complain 版本const的返回值甚至无法绑定到非std::unordered_set::at引用,更不用说对该引用进行修改了。