【问题标题】:How to call a constructor on an already allocated memory?如何在已分配的内存上调用构造函数?
【发布时间】:2009-02-06 10:33:02
【问题描述】:

如何在已分配的内存区域上调用构造函数?

【问题讨论】:

    标签: c++ constructor


    【解决方案1】:

    你可以使用placement new构造函数,它接受一个地址。

    Foo* foo = new (your_memory_address_here) Foo ();
    

    查看C++ FAQ liteMSDN 的更详细说明。唯一需要确保内存正确对齐的事情(malloc 应该返回正确对齐的内存,但要注意可能需要对齐到 16 字节边界左右的 SSE)。

    【讨论】:

    • 对于其他任何偶然发现此问题的人:我必须#include <new> 才能工作 - 如果我不这样做,g++ 会抛出一堆无用的“无匹配函数”错误。 This 是关于安置新的信息(也是 C++ 常见问题解答),它帮助我弄清楚了。
    • "The only thing" -- 还有其他问题,例如重用包含具有非平凡析构函数的活动对象的内存位置可能会导致未定义的行为。 See this question了解更多详情
    • @M.M std::launder 不能解决这个问题吗?
    【解决方案2】:

    请注意,在调用放置 new 之前,您需要在内存上调用析构函数 - 至少如果对象具有非平凡析构函数或包含具有非平凡析构函数的成员。

    对于类Foo的对象指针obj,可以如下显式调用析构函数:

    obj->~Foo();
    

    【讨论】:

    • 为什么我们要在新分配的内存上调用析构函数,然后再进行放置 new ?我不明白...
    • 您通常不会获得已分配但未初始化的内存。如果这确实是您所拥有的,那么您当然不得在其上调用析构函数。对于所有其他情况,该位置已经有一个必须妥善处理的对象。
    • 您不初始化内存(除非您的意思是设置全零)。您初始化对象。在一些随机内存上调用 dtor 是不好的。只有当你在做对象容器时,调用 dtor 才有意义。如果这些对象有空的非虚拟 dtor,你不必这样做。
    • @ArekBal Object = 内存,根据 C++ 标准。所以你初始化两者。当然,如果你有未初始化内存,你就不会调用析构函数(但那仍然是一个对象)。就像我在回答中所说的那样,空析构函数的存在不足以放弃调用析构函数,因为成员变量可能具有非平凡的析构函数。
    【解决方案3】:

    接受的答案提到的放置新构造函数是在 header 中定义的分配器类之前的旧方法。现在你真的应该这样做(以 C++11 风格):

    allocator<Foo> alloc;
    //Allocate memory for one or n objects
    auto p = alloc.allocate(1); 
    //Construct an object of Foo on allocated memory block p, by calling one of Foo's constructors
    alloc.construct(p, args, ...); 
    
    //OK, p now points to a Foo object ready for use...
    
    //Call Foo's destructor but don't release memory of p
    alloc.destroy(p); 
    //Release memory
    alloc.deallocate(p, 1); 
    

    就是这样。

    【讨论】:

    • std::allocator::construct 用于实例化由std::allocator::allocate 提供的内存中的对象,而不是任意其他来源
    • 你确定吗? @Caleth
    猜你喜欢
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 2021-07-16
    • 2019-08-12
    • 2021-08-09
    相关资源
    最近更新 更多