【问题标题】:Is there a way to remove a key from a C++ map without deleting the contents?有没有办法在不删除内容的情况下从 C++ 映射中删除键?
【发布时间】:2012-01-10 21:36:14
【问题描述】:

我有一个名为 Shape 的类和一个 ShapeStorage 类。 ShapeStorage 类有一个地图...

std::map<int, Shape*> shapes;

还有一个函数……

Shape * ReturnShapePointer(int key)  
{  
    Shape* shape = shapes[key];  
    shapes.erase(key);  
    return shape;  
}

我的目标是能够让我的主类实例化一个 ShapeStorage 对象,在形状映射中存储一些 Shape*。然后稍后我想从我的地图中删除它,但不删除值本身。我希望我的主类仍然能够访问该值。

我已经尝试过,我的指针仍然返回正确的值,但我担心,因为当我从地图中删除指针时,析构函数被调用为 Shape,所以那时它只是垃圾数据。

有没有办法解决这个问题?

【问题讨论】:

  • 我不知道你想在这里做什么。你能澄清一下ReturnShapePointer与你的文字有什么关系吗?
  • 这是一个在ShapeStorage中定义的函数,它返回一个指向形状的指针。我不希望其他类访问形状,因为我已将其设为私有。
  • “deconstructor”在C++中被称为“destructor”

标签: c++ map key


【解决方案1】:

如果您要存储指针,map 将不会调用您的析构函数。如果它被调用,它会在其他地方被调用。

尝试运行此示例:

#include <iostream>
#include <map>

class Shape {
public:
    ~Shape() {
        std::cout << "Shape deleted" << std::endl;
    }
};

int main(int argc, char *argv[]) {
    std::map<int, Shape *> shapes;
    shapes[1] = new Shape();
    std::cout << "Shape added" << std::endl;
    shapes.erase(1);
    std::cout << "Shape removed from map, now exiting" << std::endl;
}

你应该得到这个:

Shape added
Shape removed from map, now exiting

【讨论】:

    【解决方案2】:

    您的地图只包含指向Shapes 的指针。从映射中删除指针对其指向的对象没有任何影响,它只会破坏映射中的指针。

    此外,您的函数将通过键执行两次查找。一次是使用operator [],第二次是使用按键调用erase ()。这是一种更好的方法:

    Shape *ReturnShapePointer (int key)  
    {  
        Shape *shape;
        std::map<int, Shape*>::iterator it = shapes.find (key);
    
        if (it != shapes.end ())
        {
            shape = it->second;
            shapes.erase (it);
        }
        else
        {
            shape = NULL;
        }
    
        return shape;  
    }
    

    【讨论】:

    • 我在 shape 的 Shape 解构器中添加了一个虚拟打印语句,当我有线条时它会打印...shapes.erase(key);
    • 如果你的析构函数被调用,问题就出在调用它的任何代码上。 shapes.erase(key); 不会调用析构函数,它只会擦除Shape*
    • 好的 谢谢大家!我无法为任何人投票,因此我点击了“是”按钮以获取有用的帖子。
    【解决方案3】:
    Shape* shape = shapes[key];  
    shapes.erase(key); 
    
    //you can use shape here, without any problem!
    

    这很好。您可以安全地使用shape 变量。

    事实上,delete shape 是你的责任。这不是std::map的责任。

    【讨论】:

    • 我在 shape 的 Shape 解构器中添加了一个虚拟打印语句,当我有线条时它会打印...shapes.erase(key)
    • @user1075883 你怎么知道它在该行打印消息?
    【解决方案4】:

    std::map 不会自动删除它包含的指针。

    【讨论】:

    • 我在 shape 的 Shape 解构器中添加了一个虚拟打印语句,当我有线条时它会打印...shapes.erase(key)
    【解决方案5】:

    所有 STL 容器都存储 - 在你的情况下是指针。因此,当您删除条目时,不会调用 Shape 的析构函数(不是解构函数:)。

    【讨论】:

      【解决方案6】:
      Shape * ReturnShapePointer(int key)  
      {  
          Shape* shape = shapes[key];  
          shapes.erase(key);  
          return shape;  
      }
      

      恐怕因为当我从地图中删除指针时,会为 Shape 调用解构函数,

      以上代码不会删除Shape 对象。它只会将其从地图中删除,这似乎正是您想要的。

      【讨论】:

        【解决方案7】:

        当您在指针上调用擦除时,不会调用析构函数,因此您当前的解决方案应该可以正常工作。

        STL 具有值语义而不是引用语义。因此,在插入地图时会生成指针的副本。副本将消失,但您的原始文件仍将指向与它始终相同的内存位置,并且该位置中的值仍然存在,直到您通过指针删除它(或者直到该值超出范围,如果它是基于堆栈的,并且指针是使用 & 运算符设置的)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-19
          • 2015-07-30
          • 1970-01-01
          • 2012-11-01
          • 2011-04-13
          • 1970-01-01
          • 2020-12-10
          相关资源
          最近更新 更多