【问题标题】:Invalidate pointer values inside a QMap使 QMap 中的指针值无效
【发布时间】:2012-12-29 17:23:55
【问题描述】:

我遇到了一个似乎很奇怪的问题,但这可能是 QMap 工作方式的一个怪癖,我只是不明白。很难总结问题,但我会尽力而为。

我有一个班级A,有一个QMap<QString, someType*> mySomeTypeMap;。当我在我的程序中加载一个新文件时,我想删除这个QMap 的所有内容,以便我可以用新数据重新填充它。我通过执行以下操作来做到这一点:

foreach (QString key, mySomeTypeMap.keys())
{
    someType* toDelete = mySomeTypeMap.take(key);

    //Show me the original address of the pointer
    qDebug() << "toDelete: " << toDelete;

    delete toDelete;

    //Set the pointer to 0x0
    toDelete = NULL;
}

qDebug() 语句打印出我要删除的值的正确地址,当我在调试器中查看toDelete 设置为NULL 后,它显示 0x0,这就是我想要的.

然后,在另一个类B 中,我有以下代码...

void B::setSomeType(someType* blah)
{
    if (Blah != NULL)
    {
        //Calls a bunch of disconnect()'s
        disconnectAllSignals();

        Blah = blah;

        //Calls a bunch of connect()'s
        connectAllSignals();
    }
}

现在,真正令人困惑的是我的程序在到达disconnectAllSignals(); 行时崩溃了。原因是它试图在Blah 上调用disconnect(),它已被删除,当我将其设置为NULL 时应该设置为0x0。但是,如果它实际上设置为NULL,它就永远不会进入该 if 块开始。在调试器中,我看到Blah 的地址与我在设置toDelete = NULL; 之前打印出qDebug() &lt;&lt; "toDelete: " &lt;&lt; toDelete; 时得到的地址完全相同。

TLDR;在我删除指针并将相同的指针设置为NULL 后,我不知道我的程序如何取回指针的原始地址。由于稍后在执行过程中指针未设置为NULL,因此会导致崩溃。

【问题讨论】:

  • 第一个猜测:您没有遵循someType三法则。向我们展示someTye 的定义。另外,mySomeTypeMap.take(key) 返回原始元素的副本或指向元素本身的指针是什么?
  • 好吧,构造函数和析构函数都是空的……这是一个非常简单的数据类,不包含任何我需要清理的指针。我没有明确实现复制构造函数。无论如何,这将如何导致问题?并回答您的第二个问题,doc.qt.digia.com/qt/qmap.html#take
  • QMap::take(..) 从地图中删除条目,那么之后将其归零有什么意义呢?它在地图中不存在,并且副本立即超出范围。
  • Blah 来自哪里? toDelete = mySomeTypeMap.take(key) 从地图中删除索引为 key 的项目并将其存储在 toDelete 中。在您调用delete 之后,分配给toDelete(局部变量)是没有意义的。问题一定出在其他地方。

标签: c++ qt pointers memory-management qmap


【解决方案1】:

映射中的值是按值存储的,即使在这种情况下,这意味着指针(它指向的地址)是按值存储的。 例如:

someType* toDelete1 = mySomeTypeMap.take(key);
someType* toDelete2 = mySomeTypeMap.take(key);
someType* toDelete3 = toDelete1;
toDelete1 = NULL;

toDelete2 & toDelete3 仍将指向原始对象

您应该在删除后将指针从映射中删除或将该键的值设置为 NULL,而不是使指针为空。

【讨论】:

    【解决方案2】:
    someType* toDelete = mySomeTypeMap.take(key);
    

    这是一个在栈上创建的指针变量,它的值被设置为你在 map 中保存的值。您不需要将其设置为 NULL,因为它会立即超出范围。

    take 函数正在从映射中删除指针,如果您再次使用相同的键使用它,它将返回默认构造的值。就在delete之后尝试

    mySomeTypeMap.insert(key, 0);
    

    【讨论】:

    • 好的,原始类型的“默认 cunstructed 值”由 Qt 容器设置为 0,因此您不需要我回答的最后一行。问题一定出在其他地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多