当前位置: 首页 > news >正文

跟我学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还是各种的内存优化,当然也包括今天提到的就地构造等,它们都是对追求效率和安全的一种演进过程。不管是开发者还是设计者,都要多学习这种优秀的经验,不断的融会贯通,提高自己的整体的水平。
既要拿来主义,又要明白主义,博采众家之长,这才是学习的最终目的。

http://www.dtcms.com/a/109242.html

相关文章:

  • React-router v7 第二章(路由模式)
  • Vant 上传图片闪动问题的原因与解决方案
  • Shell脚本编程之大括号扩展
  • Spring 核心技术解析【纯干货版】- XX:Spring 测试模块 Spring-Test 模块精讲
  • 【文献研究】铝对热冲压加热过程中锌氧化的影响
  • 【C++ SIMD】第3篇:数据对齐与跨步访问(Windows/VS2022版)——以AVX为例
  • Hadoop集群---运维管理和技巧
  • 【Kafka基础】单机安装与配置指南,从零搭建环境
  • NodeJS--NPM介绍使用
  • 训练或微调以生成新组合结构
  • Leetcode 927 -- 思维
  • Win10定时任务计划无法显示要执行的EXE任务程序界面,问题解决办法
  • 什么是检索增强生成(RAG)
  • 7-3 逆序的三位数
  • PyTorch 深度学习实战(33):联邦学习与隐私保护
  • CROSS JOIN第一个表中的每一行与第二个表中的每一行组合
  • 商城系统:电商时代的核心驱动力
  • Cribl 修改字段rename
  • Express学习笔记(四)——同源和跨域详解
  • (九)图形管线
  • Vue3.5 企业级管理系统实战(十三):TagsView标签栏导航
  • PyQt6实例_A股日数据维护工具_权息数据增量更新线程
  • 禹神:三小时快速上手TypeScript,TS速通教程(上篇、中篇、下篇,装饰器),根据视频整理
  • Windows查重工具,强烈推荐大家收藏!
  • 前端接收客户端返回的token值使用pinia持久化保存token
  • 元素定位-xpath
  • verl单机多卡与多机多卡使用经验总结
  • MCP的基本组成部分有哪些?MCP Servers服务器起到什么作用?
  • Jetpack Compose 状态管理指南:从基础到高级实践
  • 机器学习算法分类全景解析:从理论到工业实践(2025新版)