PhonebookEntry pb1("olaNormann");
pb1.add("Home","11234567");
pb1.add("Work","11065432");
cout << pb1.getNumbers()["Home"] << endl;
cout << pb1.getNumbers()["Work"] << endl;
map<string,string>::iterator it;
for(it = pb1.getNumbers().begin(); it != pb1.getNumbers().end(); ++it){
cout << (*it).first << ": " << (*it).second << endl;
}
我使用前两个cout来确保正确添加两对。代码将使用标签Home和Work打印出前两个数字,但无法在for循环中打印这两个数字。 for循环只打印出“Home:11234567”。谁能明白为什么?下面是我的头文件,其中实现了相关方法。
class PhonebookEntry{
private:
std::string name;
std::map<std::string, std::string> numbers;
public:
PhonebookEntry(std::string name) : name(name){}
std::map<std::string, std::string> getNumbers() const {return numbers;}
void add(const std::string label,const std::string number){numbers[label] = number;}
};
答案 0 :(得分:6)
getNumbers()
正在返回地图的副本,而不是对它的引用。该副本在包含函数调用的表达式的末尾被销毁,因此在循环期间迭代器无效,并且对它执行任何操作都会给出未定义的行为。
它应该类似于:
map<string,string> & getNumbers();
^
其中&
表示引用。提供const
重载也是礼貌的:
map<string,string> const & getNumbers() const;
^^^^^^^ ^^^^^
通过此更改,您的代码应按预期工作; see demonstration
答案 1 :(得分:2)
如果这是你的方法:
std::map<std::string, std::string> getNumbers() const {return numbers;}
然后它返回numbers
地图的副本。所以在你的循环中,迭代器都搞砸了:
for(it = pb1.getNumbers().begin(); it != pb1.getNumbers().end(); ++it) { ... }
首先,它使用地图的一个副本进行初始化。然后,它与另一个副本的结束迭代器进行比较。您需要通过引用返回地图:
const std::map<std::string, std::string>& getNumbers() const {return numbers;}
答案 2 :(得分:0)
这里有两个不同的问题:
cout << pb1.getNumbers()["Home"] << endl;
您会看到输出,因为std::map<T,U>::operator[]
会返回U&
,这在调用operator<<(std::cout, U&)
时仍然有效。但是,临时表在表达式中被破坏了。
for(it = pb1.getNumbers().begin(); it != pb1.getNumbers().end(); ++it) { ... }
getNumbers()
返回的临时在循环体中无效,正如迈克在答案中解释得好。