C++定制堆内存实现——代码实现及分析

定制堆内存

实际程序调试过程中,经常需要使用堆内存,但又担心内存碎片问题,所以C++提供了一种定制内存的方法,下面针对定制堆内存详细举例说明,首先上代码,之后编译,最后分析结果。

手动定制堆内存代码

#include <iostream>
using namespace std;

class Point{
public:
  Point(int x, int y, int z):x(x),y(y),z(z){ 
    cout<<"ctor"<<endl;
  }
  ~Point(){ cout<<"dtor"<<endl;}

  virtual void print(){
    cout<<x<<" "<<y<<" "<<z<<endl;
  }

  int x;
  int y;
  int z;
};

int main()
{
   cout<<sizeof(Point)<<endl;

   void* memory = std::malloc(sizeof(Point));	//申请一个堆内存空间

  int* p1=(int*)memory;	
  for(int i=0;i<6;i++)
  {
    cout<<*p1<<" ";
    p1++;
  }
  cout<<endl;

   Point* myObject = ::new (memory) Point{100,200,300};//指定内存位置构造
   myObject->print();

  long* p=(long*)memory;
  cout<<*p<<endl;
  p++;

  int* pi=reinterpret_cast<int*>(p);	//C++强制转换
  cout<<*pi++<<endl;
  cout<<*pi++<<endl;
  cout<<*pi<<endl;
  
   myObject->~Point();	//先析构对象
   
   std::free(memory);	//释放申请的空间
}

运行结果及分析

kongcb@tcu-pc:~/testcode/memory$ g++ placement_new.cpp -o test_placement_new
kongcb@tcu-pc:~/testcode/memory$ ./test_placement_new 
24
0 0 0 0 0 0 //此处都是0,只是代表恰好这几个地址上保存的是0,并不代表每次都成立(多半是随机数)
ctor
100 200 300
4198064
100
200
300
dtor
//本系统中,一个int的长度是4,因为point有3个int,就是12字节,为啥size是24呢,因为point有虚函数,有个虚标指针地址,对齐后就成类24字节,测试将virtual void print(){的virtual去掉,size就只有12字节了。

使用STL定制对内存

//当然推荐的方式还是使用C++标准库接口实现了,代码如下:
#include <iostream>
#include <memory>
using namespace std;

class Point{
public:
  Point(int x, int y, int z):x(x),y(y),z(z){ 
		cout<<"ctor"<<endl;
	}
  
  Point(const Point& ){
    cout<<"copy ctor"<<endl;
  }

   Point( Point&& ) noexcept{
    cout<<"move ctor"<<endl;
  }
  
  ~Point(){ cout<<"dtor"<<endl;}

  void print(){
    cout<<x<<" "<<y<<" "<<z<<endl;
  }

  int x;
  int y;
  int z;
};

int main()
{

  {
    void* memory = std::malloc(3*sizeof(Point));	//申请3个类型空间堆内存

    Point* myObject = reinterpret_cast<Point*>(memory);	//堆内存指针转换为类指针,构造一次

    std::uninitialized_fill_n(myObject, 3, Point{100,200,300});	//填充类对象,构造3次
    cout<<"----"<<endl;
    //std::destroy_at(myObject);

    std::destroy_n(myObject,3);	//释放类对象,一次释放
    cout<<"----"<<endl;
    std::free(memory);	//释放空间
  }//myObject作用域结束,析构三个

   {
    void* memory = std::malloc(sizeof(Point));

    Point* myObject = reinterpret_cast<Point*>(memory);

    std::uninitialized_move_n(myObject, 1, new Point{100,200,300});//移动构造
    cout<<"----"<<endl;
    std::destroy_at(myObject);//一次释放

    cout<<"----"<<endl;
    std::free(memory);
  }//没有析构,运维之前构造的移动赋值给myObject

}

运行结果及分析

kongcb@tcu-pc:~/testcode/memory$ g++ stl_place_fill.cpp -o test_stl_place
kongcb@tcu-pc:~/testcode/memory$ ./test_stl_place 
ctor
copy ctor
copy ctor
copy ctor
dtor
----
dtor
dtor
dtor
----
ctor
move ctor
----
dtor
----

使用场景分析

对于使用需要小对象优化的地方,该方式有较好的利用效果,有利用内存的精细化管理,目前在金融和游戏等领域有较多应用(一般这些公司有专门团队负责内存优化),对于一般需求,使用C++提供的STL就能满足一般需求。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术的微光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值