请教一个 STL 的问题
map<int, int> m; m[12] = 45; // 这是怎么实现的?
它只是返回了一个int&,而且还不存在。为什么能赋值啊?
源码真的看不懂,……
map<int, int> m; m[12] = 45; // 这是怎么实现的?
它只是返回了一个int&,而且还不存在。为什么能赋值啊?
源码真的看不懂,……

llvm 真正的实现在这里
https://github.com/llvm-mirror/libcxx/blob/78d6a7767ed57b50122a161b91f59f19c9bd0d19/include/__tree#L2126
它会先寻找内部是否存在这个值,如果不存在就会构造。
它只是返回了一个 int&,而且还不存在 —— 不存在你是怎么知道的,也许这个表达式在左边的时候会自动创建呢?你预设它不存在,所以无法赋值,但明明可以赋值,那不就说明你不存在的假设是错误的吗
函数末尾有没有修饰符 const,在 C++ 里面是两个不同的成员函数。
====
但是这里有个坑。如果你操作的是可变对象,你的 value_type 有默认构造函数,如果你使用
std::cout << m[key] << std::endl;
那么如果 key 不存在,在某些版本的 STL 真的会创建出这个对象。我就被坑过。
C++11 里面加了个右值引用
“它只是返回了一个 int&,而且还不存在。为什么能赋值啊?”
“它只是返回了一个 int&”
是的, 它只是返回了一个 int&. 但这已经够了. int 是你 map value 的类型, 而 & 保证你的修改生效于 map 内部数据.
“而且还不存在”
存在的, 对于 map 的 [] 重载而言, 当你访问的元素不存在时, 会创建一个(类型的零值). 而存在时, 会返回 valueType&. 所以无论如何, 都会有元素存在.
(PS: 这里有个点需要注意, 当你想知道 map 中是否存在一个元素时, 你不能用 []. 因为这一定会存在, 你或许可以用这个类型的零值来判断是否是新创建的, 但这并不好, 更好的方式是: mapName.find(key) == maoName.end(); )
怎么这么久都没个提出来 map::operator[] 早就改用 try_emplace 定义的?
WG21 N4860
22.4.4.3 Element access
[map.access]
mapped_type& operator[](const key_type& x);
1 Effects:
Equivalent to:
return try_emplace(x).first->second;
mapped_type& operator[](key_type&& x);
2 Effects:
Equivalent to:
return try_emplace(move(x)).first->second;
真折腾源码也行,给你个现成没到处 __ 的实现好了,C++11 下实现 C++17+ API,附加保证 incomplete value_type 能用:
https://github.com/FrankHB/YSLib/blob/master/YBase/include/ystdex/map.hpp#L313
https://github.com/FrankHB/YSLib/blob/master/YBase/include/ystdex/tree.h#L1885
不过可能不如理解个外挂式 try_emplace 的逻辑顶用点:
https://github.com/FrankHB/YSLib/blob/master/YBase/include/ystdex/container.hpp#L1039