考虑以下代码:
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
返回一个常量引用:https://en.cppreference.com/w/cpp/container/unordered_map/at
所以,如果我引用unordered_map::at
的返回,我应该无法修改它的内容,对吗?还是我完全误解了const返回的含义?按照我的理解,这段代码甚至不应该编译。
现在,如果我将std::string&
更改为std::string
,我会看到复制构造函数按预期执行。程序打印123hi, 123
,表示映射中包含的值未被修改。
这里有两个问题:
- 为什么我可以修改常量引用
- 如果我使用字符串x来执行移动操作,例如
std::move(x)
(指string& x
的原始声明(,移动会按预期执行吗?还是因为const引用而最终变成了复制构造函数
unordered_map::at
返回常量引用
不,不是。它有两个重载:一个是const,一个不是。您正在使用非常量重载。
std::unordered_set::at
有两个重载,一个用于符合const
条件的实例,另一个用于不符合const
条件的实例。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
此示例显示std::unordered_set::at
的const
版本的返回值甚至不能绑定到非const
引用,更不用说正在修改的引用了。