std::map::iterator 返回值的副本还是值本身?

问题描述 投票:0回答:5

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

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
5个回答
36
投票

我想为使用 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;
}

33
投票

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

不会有副本,因为map::iterator

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


4
投票

value_type

 映射是一对,因此它有第一个和第二个成员。与所有迭代器一样,映射迭代器是一个伪指针,即它指向集合中的数据,而不是该数据的副本。

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

即使你有一个 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,则不会发生这种情况...


0
投票
迭代器,当取消引用时,

给你一个引用


0
投票
为有兴趣实验的人添加一些代码。

#include <iostream> #include <map> using namespace std; class object { public: object(int v) : m_v(v) { cout << "object() addr " << hex << this << "\n"; } object(const object& other) : m_v(other.m_v) { cout << "object(&) addr " << hex << this << "\n"; } object& operator=(const object& other) { cout << "Operator= (this addr " << hex << this << ")\n"; m_v = other.m_v; return *this; } int m_v; }; std::ostream& operator<<(std::ostream& os, object const& obj) { return os << std::to_string(obj.m_v); } int main() { cout << "Constructing:\n"; std::map<int, object> objects({{0, 0},{1,1}}); cout << "Emplace:\n"; objects.emplace(2, 2); cout << "For loop:\n"; for (const std::pair<const int, object>& i : objects) { std::cout << i.first << ": " << i.second << std::endl; } cout << "Find:\n"; const auto v = objects.find(2); if (v != objects.end()) { std::cout << v->first << ": " << v->second << std::endl; } else { std::cout << "Not found.\n"; } // your code goes here return 0; }
输出:

Constructing: object() addr 0x7ffc7e8e7aa4 object() addr 0x7ffc7e8e7aac object(&) addr 0x5617fb0eaea4 object(&) addr 0x5617fb0eaed4 Emplace: object() addr 0x5617fb0eaf04 For loop: 0: 0 1: 1 2: 2 Find: 2: 2
    
© www.soinside.com 2019 - 2024. All rights reserved.