【问题标题】:Does std::map::iterator return a copy of value or a value itself?std::map::iterator 是返回值的副本还是值本身?
【发布时间】:2011-07-19 15:28:41
【问题描述】:

我正在尝试在地图中创建地图:

typedef map<float,mytype> inner_map;
typedef map<float,inner_map> outer_map;

我能否在内部地图中放一些东西,或者 iterator::second 返回一个副本?

stl_pair.h 建议后者:

74: _T2 second;          ///< @c second is a copy of the second object

但我的测试程序运行良好,代码如下:

it = my_map.lower_bound(3.1415);
(*it).second.insert(inner_map::value_type(2.71828,"Hello world!");

那么真相在哪里?这是不是副本?

【问题讨论】:

    标签: c++ iterator stdmap


    【解决方案1】:

    我想为使用 C++11 迭代器的人添加此问题的后续答案...

    以下代码:

    std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
    for (auto i : m)
    {
        std::cout << i.first << ": " << i.second << std::endl;
    }
    

    确实复制键和值,因为默认情况下“auto”是一个值,而不是 const 引用(至少它是 clang 3.1 的行为方式)。

    另外,代码:

    std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
    for (const std::pair<std::string,std:string>& i : m)
    {
        std::cout << i.first << ": " << i.second << std::endl;
    }
    

    复制键和值,因为正确的代码应该是:

    std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
    for (const auto& i : m)
    {
        std::cout << i.first << ": " << i.second << std::endl;
    }
    

    std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
    for (const std::pair<const std::string,std:string>& i : m)
    {
        std::cout << i.first << ": " << i.second << std::endl;
    }
    

    【讨论】:

    • +1。将元素设置为 unique_ptr 将清楚地证明这一点,因为您将无法编译以访问已删除的函数(复制 ctor)。
    【解决方案2】:

    stl_pair.h 中的评论在这种特定情况下具有误导性。

    会有没有副本,因为map::iterator实际上是指地图内的原始数据value_type,它本身就是pair ),它不是副本。因此iterator::second 也指原始数据。

    【讨论】:

    • 这是真的,可以通过返回类似 myMap.find(myKey)->second 的引用来验证它。所以 stl_pair.h 中的文档不仅具有误导性,而且是错误的。
    • @xamid 好吧,这不是错误,因为stl_pair.h 文档根本没有引用std::map,它的行为方式是因为@987654329 @ 将 reference 返回到存储在地图中的 std::pair。所以对的 second 成员仍然是一个值(而不是引用),它本身就是引用。文档中的“第二个元素的副本”是指std::pair::second 拥有它在构造函数中传递的任何值的副本。
    • 看看here。引用:A reference is the object. It is not a pointer to the object, nor a copy of the object. It is the object. 参考不是副本。我理解的元素在地图中被称为“生活”,它不是传递给将其添加到地图中的函数的元素(如果已使用 emplace,它可能不存在)。
    • @xamid 我知道什么是引用,但是您将映射返回的对本身(= 引用)与其第二个成员变量(= 值,而不是引用)混淆了。这是用户传入地图的值的副本。所以地图本身在一对结构中保存了一个副本。
    • @xamid 我完全理解你,你错了:这对确实 not 持有引用,因为 second 没有引用类型。确实,地图可能包含一个以前不存在的值,但首先这个问题/答案早于移动语义,其次这并没有改变我们在这里讨论的评论不适用于 @987654335 的事实完全是@。
    【解决方案3】:

    value_type a map 是一对,因此它有 first 和 second 成员。与所有迭代器一样,map 迭代器是一个伪指针,即它指向集合中的数据,而不是该数据的副本。

    几乎可以肯定在内部包含指针而不是引用,因为迭代器可以重新分配(这就是您使用它们的目的)并且您不能重新分配引用来引用其他对象。

    即使你有一个 const_iterator 并且下面的类型是 POD,它也必须有一个指向它的指针,以防有人这样做:

    map< int, int > m;
    m.insert( make_pair( 1, 2 );
    map<int,int>::const_iterator citer = m.begin();
    map<int,int>::iterator iter = m.begin();
    iter->second = 3;
    std::cout << citer->second << '\n'; // should always print 3
    

    应该定义行为并且应该输出 3,如果 const_iterator 决定“优化”毕竟它是 const 并且只有 int...

    【讨论】:

      【解决方案4】:

      迭代器,当被取消引用时,give you a reference

      【讨论】:

        猜你喜欢
        • 2013-10-31
        • 2023-03-16
        • 2012-10-03
        • 2023-03-26
        • 1970-01-01
        • 2017-04-14
        • 2019-02-13
        • 1970-01-01
        相关资源
        最近更新 更多