【问题标题】:Using delete on pointers passed as function arguments对作为函数参数传递的指针使用 delete
【发布时间】:2009-12-10 15:19:39
【问题描述】:

删除作为函数参数传递的指针是否可以(并且合法),例如:

#include<iostream>

class test_class{
public:
    test_class():h(9){}
    int h;
    ~test_class(){std::cout<<"deleted";}
};

void delete_test(test_class* pointer_2){
    delete pointer_2;
}

int main(){
    test_class* pointer_1;

    while(true){
        pointer_1 = new test_class;

        //std::cout<<pointer_1->h;

        delete_test(pointer_1);
    }
}

现在编译得很好,但我只是想确保它会一直这样。

【问题讨论】:

    标签: c++ memory-management new-operator


    【解决方案1】:

    它总是编译不会出错。

    将指针传递给函数并在该函数中删除它是否是一件好事,这可能是另一回事,具体取决于程序的具体情况。

    您需要考虑的主要思想是指向数据的“所有权”。当您传递该指针时,调用函数是否拥有传入数据的所有权?即它是唯一可以引用此数据的地方吗?您是否放弃了指向数据的所有权,而调用函数再也没有机会再次引用数据?如果是这样,那么您必须将其删除。

    如果调用函数可能会再次引用数据,那么你不能删除它。

    如果存在通过各种数据结构对数据的其他引用,那么删除这些数据是不安全的,除非您在代码中设置了一些规则以确保您永远不会再次从这些位置引用数据。这很难做到,并且是许多编程错误的根源。

    C++ tr1 的 shared_ptr 是一个智能指针,可以在这些情况下提供帮助——它通过保持一个跟踪对数据的引用数量的引用计数来管理这个所有权概念。如果引用计数为 1,则有 1 个明确的所有者。如果引用计数大于 1,则共享所有权。如果引用计数为 0,则不再引用该数据,且 shared_ptr 将在调用 shared_ptr 析构函数时将其删除。

    【讨论】:

    • 我一直感到惊讶的是,删除指针是合法的,即使它是const
    【解决方案2】:

    是的,这是有效的。

    这通常在 C 中完成(显然使用 malloc 和 free 而不是 new 和 delete)。在 C++ 中,如果可以的话,通常最好使用其他内存管理习惯用法,例如 RAII

    【讨论】:

      【解决方案3】:

      是的,这在 C++ 中是合法的,但这样做通常不被认为是一种好的做法。对于执行newdelete 相同的类来说总是更好。

      【讨论】:

      • 我在给定代码的任何地方都没有看到“执行新”类。您可能指的是“block”而不是“class”,但这并不总是可行或有用的。
      • 但是该类可以很好地使用将指针作为参数的函数执行删除。
      【解决方案4】:

      是的,这是完全合法的。您可以从任何地方delete 一个指针,只要它指向在堆上分配的某个对象(或等于0)。

      调用者是否希望他们的对象被函数删除,这是另一个问题。

      【讨论】:

        【解决方案5】:

        这是完全合法的,但在这种情况下,使用boost::shared_ptr 之类的东西来管理内存所有权可能会更好。

        【讨论】:

          【解决方案6】:

          这样做是完全合法的。您必须确保该指针在该点之后未在调用者中使用。一般来说,执行删除的函数的名称应该表明正在发生的事情(例如,包含删除、释放、释放等)。另一个潜在的问题是确保指向的数据是用 new 而不是 new[] 分配的。

          【讨论】:

            【解决方案7】:

            它是有效的,并且在为对象编写清理方法时非常有用,尽管有 9/10 次您希望将清理逻辑放入析构函数中。

            编写单独清理的一个很好的理由是,如果您想保持对象“活着”但暂时不使用,可能在您需要一个新对象时偶尔从中提取的数组或对象池中想要构造函数开销。

            如果你要传入指针,你应该检查以确保它们不为空以避免任何未定义的行为。

            【讨论】:

              【解决方案8】:

              讨论可能有点晚了,但我想澄清一下:该函数仅获取指针的副本( fnc(int* a) 是按值传递)因此您正在删除的本地副本您传递的指针和原始指针将保持可用。

              该代码可能已被编译器优化以避免不必要的分配和删除,从而使其工作。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2012-11-28
                • 2020-11-08
                • 1970-01-01
                • 2020-09-06
                • 2021-12-18
                • 2017-03-17
                • 1970-01-01
                相关资源
                最近更新 更多