0
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;}
};
4

3 回答 3

6

getNumbers()正在返回地图的副本,而不是对其的引用。该副本在包含函数调用的表达式的末尾被销毁,因此在循环期间迭代器无效,并且对其进行任何操作都会产生未定义的行为。

它应该看起来像:

map<string,string> & getNumbers();
                   ^

其中&表示参考。提供const重载也是有礼貌的:

map<string,string> const & getNumbers() const;
                   ^^^^^^^              ^^^^^

通过该更改,您的代码应该可以按预期工作;见示范

于 2012-04-18T15:35:20.933 回答
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;} 
于 2012-04-18T15:36:37.690 回答
0

这里有两个不同的问题:

  1. 将值插入临时值并打印
  2. 在销毁后使用临时的迭代器

第一期

cout << pb1.getNumbers()["Home"] << endl;

您会看到输出,因为std::map<T,U>::operator[]返回,它在被调用U&时仍然有效。operator<<(std::cout, U&)但是,临时在表达式的 处被破坏。

第 2 期

for(it = pb1.getNumbers().begin(); it != pb1.getNumbers().end(); ++it) { ... }

getNumbers()正如 Mike 在他的回答中很好地解释的那样,循环体中返回的临时值是无效的。

于 2012-04-18T15:49:32.037 回答