定制堆内存
实际程序调试过程中,经常需要使用堆内存,但又担心内存碎片问题,所以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就能满足一般需求。