【问题标题】:When a constructor is called explicitly is the initializer and member variables constructed?当显式调用构造函数时,是否构造了初始值设定项和成员变量?
【发布时间】:2011-06-05 07:59:32
【问题描述】:

在使用“placement new”时,建议显式调用构造函数和析构函数。

在这种情况下,在类的初始化程序部分中初始化的对象是否也能正确构造?

显式调用析构函数也一样吗?成员对象是否被正确销毁?

【问题讨论】:

  • `建议显式调用构造函数和析构函数`。如何显式调用构造函数?
  • @Mahesh,void* const pmem = malloc(sizeof(test)); test* const t = new((void*)pmem) test(); 和 dtor:t->~test();
  • @ MJ - AFAIK 你可以调用析构函数,但 explicit 不应该用于构造函数。尽管在初始化列表中,您似乎正在从其派生类调用基类构造函数。如果使用关键字explicit,那么如果foo 是类名,我应该可以使用obj->foo()。但这是不允许的。我说的对吗?
  • @Moo-Juice:如果这是显式的定义,那么构造函数总是显式调用。通常我们认为构造函数在对象构造期间被隐式调用(因为构造函数没有实际名称)。可以显式调用析构函数。
  • 创建对象数组时没有显式调用构造函数。

标签: c++ constructor destructor initializer placement-new


【解决方案1】:

在使用“placement new”时,它是 建议调用构造函数和 显式析构。

说“你显式地调用构造函数”是不正确的,因为构造函数没有名字($12.1/1)。

在这种情况下,对象将 在初始化部分初始化 一个类的也得到适当的 建好了吗?

是的。你为什么怀疑它? Placement new 仅表示new 运算符不会分配任何内存,而是使用您在placement new 中传递的内存来构造对象。对象在您传递的内存中构造。

显式调用 析构函数?成员对象是否得到 正确销毁?

是的。

【讨论】:

    【解决方案2】:

    在使用“placement new”时,建议显式调用构造函数和析构函数。

    我不这么认为。它会说你需要显式调用析构函数。

    在这种情况下,在类的初始化程序部分中初始化的对象是否也能正确构造?

    除了提供内存之外,placement new 的所有其他方面都与普通 new 相同。因此,它只是使用提供的指针而不是动态分配内存。

    显式调用析构函数也一样?

    您可以(如果您觉得无能为力)在任何对象上显式调用析构函数。它将照常调用用户定义的(或编译器生成的)类析构函数。您需要为通过placement new 创建的对象显式执行此操作的原因是您可以对这些对象调用delete。这是因为 delete 假定对象是在动态分配的内存中创建的,并在调用析构函数后尝试重新循环该内存。

    成员对象是否被正确销毁?

    是的。

    如果我们这样想新的:

    // not real code
    template<class T> T* new(void* location = NULL)  (ArgumentsForT)
    {
        // If you do not provide location (normal usage)
        // then we allocate some memory for you.
        if (location == NULL)
        {    location = malloc(sizeof(T));   // Use of malloc() is just an example
        }
    
        ((T*)location)->Constructor(ArgumentsForT);
        return (T*)location;
    }
    

    因此,新展示位置将与正常新展示位置一样。
    查看调用删除

    template<typename T> void delete(T* obj)
    {
        if (obj != NULL)
        {
            obj->~T();
            free(obj);
        }
    }
    

    这里的问题是delete无法判断内存是由new分配的,还是由用户分配并传递给new的(placement new)。所以它总是在内存上调用 free 。如果您使用placement new,那么您可能没有动态分配内存(或者内存仍在用于其他用途)。

    char   x[sizeof(T)];  // don't do this (memory may not be aligned correctly).
    T*  obj = new (x) T();
    
    delete obj;  // FAIL. The memory was not dynamically allocated.
                 //       Delete will try and re-claim this memory for re-yse
                 //       Even if the memory is local.
    
     // This is why on placement new you need to call the destructor
     obj->~T();
    

    【讨论】:

    • +1 以获得更详细的答案。我认为提问者应该选择这个作为他接受的答案,而不是我的:-)
    猜你喜欢
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 2018-11-29
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多