跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 请教一个 STL 的问题
未分類
18 4 月 2021

请教一个 STL 的问题

请教一个 STL 的问题

資深大佬 : pabupa 6

map<int, int> m; m[12] = 45; // 这是怎么实现的? 

它只是返回了一个int&,而且还不存在。为什么能赋值啊?

源码真的看不懂,……

大佬有話說 (20)

  • 主 資深大佬 : pabupa

    (#`O′)喂?没人吗?

  • 資深大佬 : keygen88

    重载了[]吧,

  • 資深大佬 : jmc891205

    先插入然后赋值吧
    https://en.cppreference.com/w/cpp/container/map/operator_at

  • 資深大佬 : nightwitch

    请教一个 STL 的问题
    多看标准啊。标准明确告诉了如果 key 不存在,会先执行一次 insert 。

    llvm 真正的实现在这里
    https://github.com/llvm-mirror/libcxx/blob/78d6a7767ed57b50122a161b91f59f19c9bd0d19/include/__tree#L2126

    它会先寻找内部是否存在这个值,如果不存在就会构造。

  • 主 資深大佬 : pabupa

    @nightwitch #4 那对于只读的情况来说,不就多余了吗?而且如果 V 不能无参构造的话,不久不能用了吗?

  • 資深大佬 : hello2060

    已经忘了 c++了,这个你不是记住就行了吗?

    它只是返回了一个 int&,而且还不存在 —— 不存在你是怎么知道的,也许这个表达式在左边的时候会自动创建呢?你预设它不存在,所以无法赋值,但明明可以赋值,那不就说明你不存在的假设是错误的吗

  • 資深大佬 : hello2060

    @pabupa 只读不会插入吧。。

  • 主 資深大佬 : pabupa

    @hello2060 #7 它没有办法区分的……

  • 資深大佬 : ipwx

    只读调用 const value_type& operator[](const key_type&) const
    可变调用 value_type7 operator[](const key_type&)

    函数末尾有没有修饰符 const,在 C++ 里面是两个不同的成员函数。
    ====

    但是这里有个坑。如果你操作的是可变对象,你的 value_type 有默认构造函数,如果你使用

    std::cout << m[key] << std::endl;

    那么如果 key 不存在,在某些版本的 STL 真的会创建出这个对象。我就被坑过。

  • 資深大佬 : across

    mapped_type& operator[] (key_type&& k);

    C++11 里面加了个右值引用

  • 資深大佬 : across

    @across 哦,答歪了。 这个取值不是 const 的,返回时内部已经创建过变量了。找标准解释都有说的。
    http://www.cplusplus.com/reference/map/map/operator[]/

  • 資深大佬 : nightwitch

    @pabupa https://en.cppreference.com/w/cpp/container/map/operator_at
    仔细看标准吧。
    1. 只读的时候 map 提供了 at 函数,对于不存在的 key 会抛异常
    2. operaotr[]强制要求支持无参构造, 否则编译的时候会过不了编译。

  • 主 資深大佬 : pabupa

    @ipwx #9 谢谢,懂了……
    @nightwitch #12 我和你有仇吗?……不过还是谢谢

  • 資深大佬 : mogg

    只读用 find 判断迭代器,或者先 count 再取值
    读取一次事实上要返回两个值,是否存在和值的内容。stl 的年代还没有 std::optional ( c++17 ),没有办法表示返回多个值,总不能 map[x] = y 给你报个 error 出来吧

  • 資深大佬 : nightl2018

    只读用 find 先找一下存不存在。
    “`
    auto it = m.find(x);
    if (it != m.end() ) cerr<<*it<<endl;
    else cerr<<“Not exist.”<<endl;
    “`

  • 資深大佬 : nightl2018

    初看觉得很怪,但是结合其他 STL 标准,就相当优美。比如 set:
    “`
    set<int> s;
    if(s.insert(x).second == true) cerr<<“Insert success”<<endl;
    else cerr<<“Already exsit”<<endl;
    “`

  • 資深大佬 : Akiyu

    好像很多人都已经回答了, 不过我还是说一下吧.

    “它只是返回了一个 int&,而且还不存在。为什么能赋值啊?”

    “它只是返回了一个 int&”
    是的, 它只是返回了一个 int&. 但这已经够了. int 是你 map value 的类型, 而 & 保证你的修改生效于 map 内部数据.

    “而且还不存在”
    存在的, 对于 map 的 [] 重载而言, 当你访问的元素不存在时, 会创建一个(类型的零值). 而存在时, 会返回 valueType&. 所以无论如何, 都会有元素存在.
    (PS: 这里有个点需要注意, 当你想知道 map 中是否存在一个元素时, 你不能用 []. 因为这一定会存在, 你或许可以用这个类型的零值来判断是否是新创建的, 但这并不好, 更好的方式是: mapName.find(key) == maoName.end(); )

  • 資深大佬 : FrankHB

    @ipwx 麻烦先记清楚 map::operator[] 要求 non-const 再来科普,谢谢。

    怎么这么久都没个提出来 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

  • 資深大佬 : opentrade

    想到读研的时候有一次一个师弟问我为什么 Cpp 里函数里的局部变量外边不能访问。

  • 資深大佬 : unlighted

    cppreference.com

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具