【问题标题】:malloc and free vs new and deletemalloc 和 free 与 new 和 delete
【发布时间】:2015-01-23 08:54:11
【问题描述】:

您好,我读到 newdeletemalloc()free() 更好,因为 free() 不会调用析构函数,而 delete 会... 例如:

#include <iostream>
using namespace std;

class String
{
public:
    String();
    String(const String&){cout<<"String cpy ctor\n";}
    ~String();
private:
    int* itsParray;
};

String::String()
{
    cout<<"String ctor\n";
    itsParray=new int[100];
    for(int i(0);i<100;i++)
        itsParray[i]=i+1;
}

String::~String()
{
        cout<<"String dtor\n";
        delete[] itsParray;
        itsParray=NULL;
}

int main()
{
        String* pStr=NULL;
        pStr = static_cast<String* > (malloc(4 * sizeof(String)));
        free(pStr);

        pStr=new String[4];
        delete[] pStr;

        cout<<endl<<endl<<endl;
        return 0;
}

当我执行程序时,我看到在pStr 上调用delete 时调用了四个String 对象的析构函数。但是free() 删除的四个不调用析构函数。这是否意味着free()只要类内部的堆上有指针就会导致内存泄漏?

【问题讨论】:

  • 我猜你的意思是“新建并删除”。
  • mallocfree 都是 C 函数,而不是 C++ 函数。你不应该在 C++ 代码中使用它们,除非你实际上是在为 C 库分配东西——在这种情况下,newdelete 应该可以正常工作。
  • 这意味着应该调用的析构函数不是。这可能导致未定义的行为。另外,不要专注于内存泄漏。类可以管理非内存资源。
  • 另外,free() 不会导致内存泄漏,在 C++ 代码中使用free() 的糟糕程序员会这样做。
  • 不仅free 不会调用对象的析构函数,而且malloc 也不会调用对象的构造函数。

标签: c++


【解决方案1】:

new 调用构造函数,malloc() 没有。 delete 调用析构函数,free() 没有。如果有问题的类在内部分配内存,那么是的,您可能会遇到内存泄漏。

如果你必须使用 malloc()free()(在 C++ 中,你真的不应该),你将不得不使用 placement new 来调用构造函数,并调用自己析构,例如:

pStr = static_cast<String*>(malloc(4 * sizeof(String)));
if (pStr)
{
    for (int i = 0; i < 4; ++i)
        new (&pStr[i]) String;
    ...
    for (int i = 3; i >= 0; --i)
        pStr[i].~String();
    free(pStr);
}

如果你真的需要模仿new[],你应该处理构造函数抛出的异常,例如:

pStr = static_cast<String*>(malloc(4 * sizeof(String)));
if (!pStr)
    throw std::bad_alloc("");

int numConstructed = 0;
try
{
    for (int i = 0; i < 4; ++i)
    {
        new (&pStr[i]) String;
        ++numConstructed;
    }
}
catch (const std::exception &)
{
    for (int i = numConstructed-1; i >= 0; ++i)
        pStr[i]).~String();
    throw;
}

...

for (int i = numConstructed-1; i >= 0; --i)
    pStr[i].~String();
free(pStr);

【讨论】:

    【解决方案2】:

    是的。对于 C++ 对象,您必须使用“新建”和“删除”。 'new' 将确保调用对象的构造函数,而 'delete' 将确保调用对象的析构函数。

    malloc() 和 free() 是内存分配例程(来自 C 世界),但不会调用构造函数或析构函数。如果这些对象自己分配内存(无论是在构造函数中,还是在它们的生命周期中),大概析构函数会释放该内存,但为了确保发生这种情况,您必须使用“删除”来调用析构函数。

    另外,不要将 new/delete 与 malloc/free 混用。也就是说,不要在同一对象上使用“new”后跟 free(),或者不要在 malloc() 后跟“delete”。它不会起作用。

    仅供参考,'new' 可以通过 malloc() 来实现,然后调用对象的构造函数。 'delete' 可以在调用对象的析构函数后以 free() 的形式实现。事实上,如果您编写特定于类的“new”和“delete”方法,那么您就是这样做的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-02
      • 2017-01-02
      • 2016-04-28
      相关资源
      最近更新 更多