指向结构的指针保留某些属性,同时将其他属性重置为零(使用地图)

时间:2018-01-24 05:28:38

标签: c++

我使用map来存储键和指向链表中节点的指针。 创建映射后,我使用MyMap.find(key)来获取所需条目的迭代器。使用MyItr->秒我检索指向节点的指针。 但是当我访问存储在该节点的值时,该值设置为零。

MyMap定义为

map<int,Node*> MyMap; //map the key to the node in the linked list

结构如下:

struct Node{
Node* next;
Node* prev;
int value;
int key;
Node(Node* p, Node* n, int k, int val):prev(p),next(n),key(k),value(val){};
Node(int k, int val):prev(NULL),next(NULL),key(k),value(val){};
};

功能集如下:

void set(int key,int value)
{

    if(counter<cp)
    {
        if(counter==0)
        {
            Node node(0,0,key,value);
            MyMap.insert(pair <int,Node*> (key,&node));
            head=&node;
            node.next=&node;
            node.prev=&node;
            prev_node=&node;
        }
        else
        {
            Node node(prev_node,head,key,value);
            MyMap.insert(pair <int,Node*> (key,&node));
            tail=&node;
            //tail=&node;
        }
        counter++;
    }
}

这是我的get(key)函数,用于返回值:

int get(int k)
{

        //Node* node;
        Myitrerator=MyMap.find(k);
        if(Myitrator==MyMap.end())
        {
            return -1; // return -1 if not found
        }
        else
        {
            Node* np1=Myitrator->second;
            return np1->value; // value to the corresponding key 
            // this always return 0 even if the address returned
            //by Myiterator matches in debugger 
        }

}

这是主要功能:

int main() {
int n, capacity,i; // capacity of Cache 
cin >> n >> capacity;
LRUCache l(capacity); // LRU is class contaning functions and map
for(i=0;i<n;i++) {
    string command;
    cin >> command;
    if(command == "get") {
        int key;
        cin >> key;
        cout << l.get(key) << endl;
    }
    else if(command == "set") {
        int key, value;
        cin >> key >> value;
        l.set(key,value);
    }
}
return 0;
}

Set(key,value)函数为链表创建新节点,并使用键将指针添加到地图中的该节点。

我知道双向链接列表没有正确实现,但是现在这并不是我所关心的,因为没有遍历列表来获取值。 我哪里错了?

1 个答案:

答案 0 :(得分:0)

您的set()函数存储指向Node变量的指针,这些变量在堆栈的自动内存中实例化。当set()退出时,变量超出范围,销毁Node对象并将指针留在map悬空中,因此当get()尝试访问它们时它们无效。您的代码有未定义的行为

您需要更改set()以使用Node运算符在堆上的动态内存中分配new个对象。

void set(int key,int value)
{
    if(counter<cp)
    {
        if(counter==0)
        {
            Node *node = new Node(0,0,key,value); // <--
            MyMap.insert(std::make_pair(key,node));
            head=node;
            node->next=node;
            node->prev=node;
            prev_node=node;
        }
        else
        {
            Node *node = new Node(prev_node,head,key,value); // <--
            MyMap.insert(std::make_pair(key,node));
            tail=node;
        }
        counter++;
    }
}

在某些时候,当你完成使用它们时,你将不得不迭代map销毁Node个对象:

for(std::map<int,Node*>::iterator iter = MyMap.begin(); iter != MyMap.end(); ++iter) {
    delete iter->second;
}

如果您使用的是C ++ 11或更高版本,您可以考虑使用std:::unique_ptr(或std::shared_ptrstd::weak_ptr,因为您正在创建链接列表)以让编译器处理当map被销毁时,你会破坏节点:

std::map<int,std::unique_ptr<Node>> MyMap;

void set(int key,int value)
{
    if(counter<cp)
    {
        if(counter==0)
        {
            std::unique_ptr<Node> node(new Node(0,0,key,value)); // <--
            MyMap.insert(std::make_pair(key,std::move(node)));
            head=node.get();
            node->next=head;
            node->prev=head;
            prev_node=head;
        }
        else
        {
            std::unique_ptr<Node> node(new Node(prev_node,head,key,value)); // <--
            MyMap.insert(std::make_pair(key,std::move(node)));
            tail=node.get();
        }
        counter++;
    }
}

int get(int k)
{
    auto Myitrerator = MyMap.find(k);
    if (Myitrator == MyMap.end())
        return -1; // return -1 if not found

    return Myitrator->second->value; // value to the corresponding key 
}