使用基于auto的范围for循环 vs 使用基于pair的范围for循环

3
在下面的代码中
#include <iostream>
#include<unordered_map>
#include<string>

int main()
{
    std::unordered_map<std::string,int>m;
    m["1"]=1;
    m["2"]=2;

    for(const std::pair<std::string,int>&p :m)
    {
        std::cout<<&p<<"\n";
        /*0x7fff5fbff068
          0x7fff5fbff068*/
    }

    for(const auto &p :m)
    {
        std::cout<<&p<<"\n";
        /*0x10061e410
         0x10061e3e0*/
    }

}

如果我使用普通的基于对偶的范围for循环,它会显示相同的地址用于两次迭代。
0x7fff5fbff068
0x7fff5fbff068

如果我使用auto,地址对于迭代都会发生变化。

/*0x10061e410
  0x10061e3e0*/

为什么行为有差异。即使在使用pair的循环基础上,两者都应该显示不同的地址。

这两种范围for循环之间有什么区别?


1
它们是不同的类型,但我不确定为什么:https://wandbox.org/permlink/GgzHEl03DQdbsoiO - xaxxon
3
类型应为 std::pair<const Key, T> - kmdreko
1个回答

6

事情是这样的。你的两个循环没有使用相同类型的元素。

map迭代器返回对std::pair<const std::string, int>1的引用。而你的第一个循环构造了一个临时对象(因为你的std::string没有const修饰)。因此,在第一个循环中,你并没有打印出map内部的pair的地址。

编译器可能会巧妙地使用相同的存储空间来构造每次迭代的临时对象,所以你总是看到相同的地址被打印。


1记住,你不能通过迭代器修改key。否则,它将破坏map的不变性。


你的意思是每次在循环中它都会创建一个新的临时对象吗?如果不小心使用同一个临时对象...如果我添加std::pair<const std::string,int>,就不会创建任何临时对象了.. - Hariom Singh
@HariomSingh - 你说的"use std::pair<const std::string, int>"是什么意思?如果元素类型没有声明为引用,你仍然会有临时变量。 - StoryTeller - Unslander Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接