跟我学C++中级篇——In-Place Construction 和placement new

一、In-Place Construction

In-Place Construction,就地构造或原地构造。它是什么意思呢?就是在最终使用 个对象的内存处直接创建对象。为什么会这样做?有什么目的?大家都知道,对C/C++来说,性能在开发中是一个重要的考量因素。在前面的一些优化的过程,都提出过各种的内存优化。比如返回值优化(RVO,NRVO),就可以减少对象的拷贝动作。而std::move和移动拷贝构造函数都可以减少临时对象的创建。
在前面分析一些STL的容器接口中,提出过尽量使用emplace_back而不使用传统的insert等,其中一个重要原因也是如此。

二、placement new

在看到前面的就地构造,会不会想起placement new操作符,在前面的分析中可以知道它可以在指定的内存上进行对象的构造,这是不是和In-Place Construction有些相通的味道。但placement new使用起来有些不方便,除了自己要搞定内存的控制外,生成对象的构造函数还需要开发者自己管理。
好,既然明白了有味道相似,那么就可以猜测到它们之间肯定存在着一些什么关系。
c++内存分配的管理中分析过,launder和start_lifetime_as

三、二者关系和应用场景

在前面的文章“c++17的launder”和“launder和start_lifetime_as”中都提到了placement new,也可以看到它们和In-Place Construction有些类似的使用方式。其实,仔细的分析会发现,In-Place Construction底层就是使用placement new来实现的。可以这样理解,In-Place Construction是上层抽象的封装应用,而placement new是底层的真正实现。举一个不太恰当的例子,正如new和 malloc的行为逻辑有些相似,new底层调用了malloc。
在很多的应的场景下,内存可能需要反复的创建和释放。这很容易产生内存碎片或严重影响效率。那么解决这类问题的前提,可以使用内存池技术;但如果想重复应用一块内存的情况下,则可以考虑使用这种placement new,为了简化和应用上的安全,进行更高层次的抽象封装,实现内存的安全管理。则可以使用In-Place Construction。
说了这些,哪些常见的情况下会有这种应用呢?
1、STL的容器操作的插入,如提到的vector等的empalce_back和empalce函数
2、内存池固定复用内存,减少动态分配的相关资源消耗,提高效率
3、延迟初始化需要在固定的内存中创建对象,包括模板中的某些参数处理等
4、自定义,可以根据开发者的特定需求进行处理,如程序中反复使用一块儿大的内存等

四、实例分析

下面看一个placement new例子:

#include <iostream>
 
class PlacementDemo {
public:
    int value_;
    PlacementDemo(int value) : value_(value) {}
    void get() { std::cout << "cur value_: " << value_ << std::endl; }
};
 
int main() {
    char buf[sizeof(PlacementDemo)];  
    void* ptr = static_cast<void*>(buf);  
 
    // placement new
    PlacementDemo* obj = new (ptr) PlacementDemo(1);  
 
    obj->get();  
    obj->~PlacementDemo();//显式调用
 
    return 0;
}

再看一个STL容器中In-Place Construction的例子:

#include <vector>
#include <string>

int main() {
    std::vector<std::string> vec;
    vec.emplace_back("demo"); //  vector 的尾部内存中原地构造 std::string对象
    return 0;
}

大家还可以翻一翻刚刚提到的前面几篇文章,对照学习,会有更大的收获。

五、总结

技术的进步不是一朝一夕完成的,它一定是从需求出发,不断的进行完善,然后被抽象出来。无论是RVO还是各种的内存优化,当然也包括今天提到的就地构造等,它们都是对追求效率和安全的一种演进过程。不管是开发者还是设计者,都要多学习这种优秀的经验,不断的融会贯通,提高自己的整体的水平。
既要拿来主义,又要明白主义,博采众家之长,这才是学习的最终目的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值