简单的 CPP 地图存储和访问无法按预期工作

simple cpp map store and access not working as expected

本文关键字:工作 访问 CPP 地图 存储 简单      更新时间:2023-10-16

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

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

输出-

映射键 = 2:节点键 = 32764,值 = -491659096

注意 - 输出键和值不断变化,并且每次运行都不固定。

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

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

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

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

C++还有第二个选择:某些数据的生存期可以由类控制。 例如,您输入的intNode*mpmp一起被删除。 因此,您可以直接存储Node而不是其地址,而不是将Node*存储在 mp 中!

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中,如果您希望在多个位置mp中使用某些Node对象,则std::shared_ptr<Node>很有用。

如果您只想引用已知生命周期的对象,并且希望将该引用存储在其他生命周期较短的对象中,则使用&获取对象的地址(例如创建Node*)非常有用。

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

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

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

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