尝试重置指针时有趣的问题

时间:2011-07-12 06:13:40

标签: c++ visual-studio-2010

由于我的C ++不是很好,这可能是一个非常简单/明显的答案,但它肯定让我难过。请记住它有点晚了,我有点累了。我在这里得到了这段代码:

void TestFunc(int *pVar)
{
    cout << endl << *pVar << endl;
    delete pVar;
    pVar = nullptr;
}

int main(int argc, char *argv[])
{
    int *z(new int);

    *z = 5;
    TestFunc(z);
    if (z == nullptr)
        cout << "z Successfully Deleted!" << endl;
    else cout << "z NOT deleted!" << endl;
    return 0;
}

程序编译得很好,没有错误或警告。当我运行它时,它会显示5,就像我期望的那样。但是,它说z NOT deleted!。我很好奇为什么pVar没有被设置为nullptr,即使我明确地在我的TestFunc()函数中设置它。任何帮助,将不胜感激。如果重要,那么这就是Visual Studio 2010,而只是一个常规的非托管C ++应用程序。

4 个答案:

答案 0 :(得分:5)

因为通过值传递(即作为副本)。

如果您希望传递变量本身(而不仅仅是其复制的值),请使用

void TestFunc(int *&pVar)

代替。

请注意,delete仅关注指针,而不关心指针。因此,“删除”指针的副本会删除与原始指针相同的内容,因为在任何一种情况下,您都要删除它们的目标,这些目标是相同的。

答案 1 :(得分:2)

TestFunc按值接受指针,因此在函数内部将其设置为null实际上只会影响函数中的副本,并且对调用者不可见。因此pVar设置为空,但z中的main()不是因为它们是不同的变量。

要使调用者看到更改,请通过引用或双指针传递指针。

答案 2 :(得分:1)

已经很晚了(抱歉!!!)。

z按值传递。 z不是pVar。您已将nullptr的值分配给pVar,而不是z

答案 3 :(得分:0)

您提出的“成语”通常被称为安全删除

它已经在C中已知(虽然当时它是free):将刚刚释放/删除的指针清零以避免这样做两次。

麻烦的是,你将当前的指针归零,但它的任何副本仍然指向相同的内存区域,现在它包含垃圾。

内存处理是一个难题,基本概念是所有权。在任何时候,都应该很好地识别特定内存区域的所有者,他们应该负责在适当的时候将其返回给系统。

这方面的第一步是使用智能指针,例如std::unique_ptrboost::scoped_ptr。对于共享所有权(仅限专家),std::shared_ptr可能会派上用场,但您还没有。

如果您在代码中写了delete,则表示您正在暴露自己。它本身并不坏,但它需要仔细审查,并使代码变得脆弱(即,可能会在更改时中断)。在你的情况下:

int main() {
  boost::scoped_ptr<int> i(new 5);
  foo(*i);
} // memory returned to system by ~scoped_ptr()