c ++ malloc和自由对象的创建和删除

时间:2015-10-08 20:03:31

标签: c++ malloc free

我将首先用C ++发布我的测试程序:

#include <iostream>
using namespace std;

class X
{
     int x;
     public:
     X()
     {
       cout<<"constructing\n";
       x=0;
     }
     int& getx()
     {
       return x;
     }
     ~X()
     {
       cout<<"destroying\n";
     }
};
int main()
{
     X* p=(X*)malloc(sizeof(X));
     ++p->getx();
     p->getx()*=5;
     cout<<p->getx();
     free(p);
     return 0;
}

输出:

5

现在,在有人抱怨为什么我使用malloc&amp;在{+ 1}} C ++程序中,我想重申它只是一个测试程序,即使使用free&amp; operator new。但我的问题仍然是:

  1. 即使使用operator delete没有创建X的对象,我们如何才能访问类X的变量x?
  2. 显然malloc or operator new也不会破坏对象并执行纯粹的分配。如果我使用free & operator delete创建对象但使用new而不是operator delete or free会发生什么?我的目标是否仍然在那里&amp;它还可以使用吗?

3 个答案:

答案 0 :(得分:12)

  1. 如果通过调用new解除分配使用free()创建的对象,则您将深入到未定义的行为。同样,如果您使用malloc()取消分配delete&lt; ed}对象,则表示您有未定义的行为。无论你做什么,都不要混淆两者。

  2. malloc()具有与new不同的语义:malloc()只分配内存,不调用构造函数。 new执行分配,并调用适当的构造函数。

    同样,free()delete之间存在模拟差异:delete在释放内存之前调用析构函数,free()没有。

  3. 您可以在C ++中使用malloc()来支持真正的C ++对象,但您必须自己进行构造函数/析构函数调用:

    //The placement-new below needs this:
    #include <new>
    
    //This is what new does:
    char* temp = (char*)malloc(sizeof(Foo));    //allocation only
    Foo* foo = new(temp) Foo();    //placement-new: construction only
    
    //This is what delete does:
    foo->~Foo();    //destruction only
    free((void*)foo);    //deallocation only
    

    请注意,第二行中的placement-new语法是在C ++中显式调用构造函数的唯一方法。可以像任何其他成员一样显式调用析构函数。这种不对称的原因是对象在销毁之前确实是一个有效的对象,而在构造之前并不是这样。

    关于p->getx()编译原因的问题。这取决于您的代码中的这个小演员:

    X* p=(X*)malloc(sizeof(X));
          ^
          |
    this little cast
    

    在这里,程序员明确地告诉编译器:&#34;我知道我给你的值看起来不像指向X,但我告诉你它是。所以,愚蠢的编译器,只是关闭类型不匹配,并将其视为指向X的指针,因为我,人类,你的上帝,告诉你了!&#34;

    那么你的编译器能做些什么呢?它会关闭类型不匹配,并将指针视为指向X的指针,正如您所说的那样。如果这是错的,这就是你的问题。也许程序运行正常,也许它会崩溃,也许它会默默地破坏数据,也许会出现粉红色的大象。你的编译器不关心。唯一关心的是它是你的愿望。编译器可以非常听话。

答案 1 :(得分:3)

回答这部分问题:“如果我使用new创建一个对象但使用operator delete或free而不是删除会发生什么?我的对象是否仍然在那里&amp;它仍然可用吗?”

使用malloc分配并使用delete释放是未定义的行为。在调用对象的析构函数后,无法保证实现将使用C free

同样相反。如果使用new进行分配,则无法保证返回的指针来自内部调用的mallocrealloccalloc,只有通过它才能安全通过的情况指向free的指针。

即使它有效,也可能会破坏程序和/或泄漏资源,因为你要么跳过对象的构造函数或析构函数。

编辑:

你说“显然免费&amp;运营商删除也不会破坏对象并执行纯粹的分配。”嗯,那是错的。 delete将调用object的析构函数,因此它将销毁然后解除分配。

至于评论中澄清的问题,“为什么你仍然可以访问x”,好吧,malloc将分配对象占用的全部空间(在你的情况下,我认为只是x变量),变量将在那里,只有构造函数不会被调用,因此,它的值不会被设置为零。如果你在运行程序时最初为零,那只是巧合。

答案 2 :(得分:1)

从这么多人那里读了很多分,我自己写了一个程序来解释你的问题。见下文: -

p

了解v如何忽略了向量executed并转到了行vector<int>。这是因为class永远不是由class template创建的operator new (or malloc in your case)(或更确切地说是x)。你的程序显示了operator new or malloc的输出,因为它是一个原始类型&amp;不是一个班级。对于一个类,你需要一个构造函数&amp;因此operator new with new不适合课程和课程。因此输出。如果您只是替换operator delete with delete&amp; constructing 5 1 2 executed destroying 然后输出将是: -

malloc & free

现在你的代码给出了正确的&amp;合适的结果!刚果!

对于你的第二个问题,永远不要与new & delete混淆public class AllProductsCategoryPage extends BasePage{ public AllProductsCategoryPage(WebDriver driver) { super(driver); } public void getData() throws InterruptedException { List<String> prices; } } ,因为它会创建UB并且不会发生结果。