C++ 动态内存管理 new delete allocator shared_ptr

1.在C++的程序中会有下面几块不同性质的内存来管理程序:

静态内存:用来保存局部的static对象,类的static数据成员,定义在函数外的全局变量。静态内存在程序启动时开辟在程序结束时释放。由编译器自动创建和销毁。

栈内存:用来保存函数内的非static对象(不包括用new开辟空间生成的对象)。在进入函数时开辟,才函数结束时释放。由编译器自动创建和销毁。

堆内存:用来存储动态分配的对象,比如在C++中用new关键字创建的对象就放在堆内存中。这种动态对象的生存周期由程序自身控制。也就是说用new关键字创建的对象,需要我们手动去释放它所开辟的内存。比如在函数中用new声明了局部变量,如果没有手动释放该对象,那么即使函数运行完毕后该对象还是不会被销毁。

 

2.new和delete

new用于手动分配内存创建一个动态对象,它的返回值是一个对象的指针:

int* i = new int();
Person* p = new Person();
Person* p = new Person[10];//new一个数组的时候返回的是对象的指针,指向数组的首元素
delete用来销毁用new创建的动态对象释放内存:
int* i = new int();
delete i;
Person* p = new Person();
delete p;
Person* p = new Person[10];
delete [] p;//当销毁一个数组动态对象时需要加上[]
 
3.allocator的使用,头文件:#include <memory>
(1)使用new创建动态对象的时候,必须在分配内存的时候就对其进行初始化,就是在new的时候就会调用构造函数,同样delete的时候就会调用析构函数。
(2)如果我们希望创建动态对象,并且将其为这个对象分配内存和初始化分开执行,就需要使用allocator
(3)创建动态对象用法:
 std::allocator<string> alloc;//创建一个allocator对象它用来为分配string类型的对象分配内存
    std::string* p = alloc.allocate(10);//分配一个可以存储10个string对象的内存空间,返回的p指针指向可以存储的第一个string对象
    std::string* p1 = p;
    alloc.construct(p1,"hi");//为分配的内存中的第一个string对象初始化,这里第一个参数是指向这个内存位置的指针,后面就是string的构造函数支持的参数,只要string本身支持的构造方法这里都可以使用其来初始化p1
    cout<<*p1<<endl;
    std::string* p2 = p;
    alloc.construct(p1,10,'a');//为分配的内存中的第二个string对象初始化
    cout<<*p2<<endl;
(4)销毁动态对象:
首先要销毁在申请的这段内存中初始化赋值了的对象:
 alloc.destroy(p1);
 alloc.destroy(p2);
然后回收分配的那段内存:
alloc.deallocate(p,10);//这里的p是申请内存时返回的指针,10是申请时写入的长度
 
4.智能指针的使用,头文件:#include <memory>
(1)为了简化动态对象的管理,新的标准库提供了智能指针的用法,使用智能指针他会自动释放我们动态对象使用的内存
(2)智能指针分为三种:std::shared_ptr允许多个指针指向同一个对象,std::unique_ptr独占所指向的对象,std::weak_ptr指向std::shared_ptr所管理的对象
(3)创建智能指针:
std::shared_ptr<int> ptr;//ptr中保存一个空指针
推荐使用make_shared函数来创建智能指针:
std::shared_ptr<std::string> ptr = std::make_shared<std::string>(10,'a');//make_shared支持所有该类型的构造函数
(4)shared_ptr的计数功能,每个shared_ptr都有关联的计数器,当用一个shared_ptr初始化另一个shared_ptr时或者拷贝赋值或者作为函数参数传递或者作为返回值返回等,都会让这个计算器+1。当销毁这个shared_ptr指针对象时(一个局部shared_ptr离开作用域时)会让计数器-1。
当这个计数器减少为0时,就会自动去销毁这个智能指针指向的对象,从而实现自动销毁释放对象的功能。shared_ptr有一个use_count()函数用来返回这个计数器的值。
(5)可以使用new创建的动态对象初始化智能指针,默认会使用delete来销毁这个动态对象:
std::shared_ptr<std::string> ptr2(new string("ssssssss"));
也可以将普通指针放入括号里面来创建一个动态指针,但是没必要这样做,因为这样使用后反需要我们自己提供delete来销毁这个对象。
(6)不要混用普通指针和智能指针!!!
如果将一个智能指针绑定到一个普通指针之后,就将这个指针的内存管理交给了智能指针,也就是说如果这个智能指针被销毁后,普通指针有可能就访问不到自己指向的内存了。
posted @ 2021-04-27 16:45  maycpou  阅读(214)  评论(0编辑  收藏  举报