简单的cpp映射存储和访问不能按预期工作

时间:2018-03-01 16:07:27

标签: c++

我有以下代码,它使用map根据将节点插入 mp 。该类有两个函数 set get 分别插入和访问映射。

struct Node {
  int value;
  int key;
  Node(int k, int val):key(k),value(val) {};
};

class Cache {
  private:
    map<int, Node*> mp;
    Node* tail;
    Node* head;
  public:
    void set(int, int);
    void get(int);
};

void Cache::set(int key, int value) {
  Node newN = Node(key, value);
  mp.insert(std::pair<int, Node*>(key, &newN));
}

void Cache::get(int key) {
  auto s = this->mp.find(key);
  if (s != this->mp.end()) {
    Node *nHit = s->second;
    std::cout << "Map key = " << s->first;
    std::cout << " : Node Key = " << nHit->key;
    std::cout << ", value = " << nHit->value << "\n";
  }
}

下面是驱动程序主要功能实现,它接受2行输入并输出键和值。

int main() {
  int i;
  Cache l;
  for(i = 0; i < 2; i++) {
    string command;
    cin >> command;
    if(command == "get") {
      int key;
      cin >> key;
      l.get(key);
    }
    else if(command == "set") {
      int key, value;
      cin >> key >> value;
      l.set(key, value);
    }
  }

  return 0;
}

输入 -

  

设置2 3

     

得到2

输出 -

  

Map key = 2:Node Key = 32764,value = -491659096

注意 - 输出键和值会不断变化,并且不会在每次运行时修复。

为什么以及如何更改地图的键和值?

3 个答案:

答案 0 :(得分:1)

您正在插入指向函数范围值的指针。当函数set()退出时,newN被销毁,并且地图中保存的指针无效。

要么你真的想要一个带有Node实例的地图作为价值;或者你需要在set()中使用new来分配你的对象,但是你还需要记住删除它。您可以使用“智能”指针(例如shared_ptr或unique_ptr)来帮助管理此生命周期 - 尽管unique_ptr不会比使用实例更有优势。

答案 1 :(得分:0)

在C ++中,一段数据通常绑定到一个位置。如果该位置是某个{ block scope; }中的变量,则在结束}处删除该变量。例如,Cache::set的右括号会删除newN,对它的任何引用(包括mp中的指针)都不再指向任何位置。

C ++有第二种选择:某些数据的生命周期可以由一个类控制。例如,您放入int的{​​{1}}和Node*值与mp一起被删除。因此,不是将mp存储在mp中,而是直接存储Node*,而不是其地址!

Node的声明应为

mp

您可以使用

进行插入
map<int, Node*> mp;

然后在void Cache::set(int key, int value) { mp.emplace(key, Node(key, value)); } 中你可以拥有

main

然后,您可以Node &nHit = s->second; 成员nHit而不是.

另一种选择是使用智能指针,正如Jesper Juhl所说。将->存储在std::unique_ptr<Node>中,如果您只使用指针进行虚拟方法的多态操作,mp如果您想要使用某些std::shared_ptr<Node>个对象则非常有用在几个地方 Node

如果您想要引用已知生命周期的对象,并且想要将该引用存储在某些内容中,则使用mp(例如创建&)对象的地址非常有用生命周期较短的其他对象。

请勿在智能指针构造函数中使用Node*,除非您已准备好自己单独new Node(key, value) 每个 delete,并且永远不要错误。

答案 2 :(得分:-1)

您必须使用new分配节点。如,

Node *newN = new Node(key, value);
mp.insert(std::pair<int, Node*>(key, newN));

因为它是你的节点在堆栈上并且在函数返回时超出范围。