C++中的内存管理,new/delete, shared_ptr/unique_ptr

  1. 内存:常用的是static memory 和stack memory。 static memory是用来存放local static objects、类中的静态数据成员、定义在任何函数之外的变量(static中的变量在使用之前就已经分配了空间,而且其生命周期是整个程序的运行过程)。stack memory用来存放的是函数内部的非静态变量(因为栈也叫函数调用栈,存放的是函数中的auto变量,函数退出时,需要将这些变量也从栈中清除,所以其中存储的变量的生命周期只是在该函数中,因此必然存放的是该函数中的非静态变量,当然还有函数返回地址,实参列表等)。这两种内存是可以自动的分配和回收的。  另外还有一种dynamic memory是用来动态内存分配的叫做heap(堆),heap中存储的是在运行过程中才分配内存的对象,其生命周期由程序负责控制(分配和释放都是程序来完成,而非编译器)

  2. 通常在C++中申请和释放动态内存(堆)使用的是一组关键字new和delete。但是,它们是有问题的,因为,一是很难保证空间在适当的时候被释放了,二是有可能会去释放仍然有其他指针指向该内存的空间。

  3. library中在memory头部定义了了两个smart pointer来自动地管理动态内存。shared_ptr(还定义了一个weak_ptr), unique_ptr。smart pointer也和vector一样是模板。用作类型创建对象的时候需要加上, 如shared_ptr p1; //shared_ptr that can point at a string

  4. shared_ptr: 允许多个指针指向相同的对象。最安全的方法是调用函数make_shared 进行分配。如shared_ptr p2 = make_shared(4). shared_ptr定义的创建的对象有一个指针reference count,无论什么时候拷贝shared_ptr的指针的时候,count都加1. 当给shared_ptr的指针赋了新值或者shared_ptr失效的时候,count减1。 当count等于0的时候,shared_ptr指向的对象自动释放空间。所以关键是创建的对象中维持了一个引用计数,来追踪所有指向该段空间的指针。如果计数的值为0,表示没有指针指向该对象,就释放掉

  5. 例如:

    auto r = make_shared<char>(4);
    r = q; //after this, system will release the four bytes memory.
  6. 为什么能够自动释放内存: 必须提到constructor和destructor,constructor是分配内存,初始化对象的时候使用的,destructor是释放空间,摧毁对象用的。在shared_ptr中有一个destructor,该destructor记录了对象的引用计数,当引用计数为0的时候,就释放掉该对象的空间。

  7. 什么时候使用动态内存:

     1)不知道要申请多少个对象(比如在一个for循环中,循环次数不一定)

        2)不知道对象的精确的类型(比如写了一个模板函数)

        3) 需要在不同的对象之间共享数据(最常用的)

  8. 研究一下vector(stl中定义的一个容器)中使用的是哪里的内存? 按照7的三个使用动态内存的条件,vector应该属于不知道要多少空间来存放对象。因此,应该属于动态内存方面的问题。 那么应该如何地创建和释放内存呢?vector中有两个函数,size()和capacity(),size()表示容器中有多少个数据,capacity()表示容器中最多放置多少个数据。另外可以使用clear来释放容器中的数据。但是根据下面的实验可以看出,使用clear只是释放掉了容器中的数据项,但是并没有释放容器占有的空间。即容器在不断地伸长地过程中不断地申请的新的空间并没有释放。仍然被这个容器占用。可以使用shrink_to_fit() 使得占有的空间等于容器中实际的数据项,或者使用reserve(n)使得分配至少n的元素的空间。(但是根据C++ primer中所说,shrink_to_fit()只是一个请求,并不保证一定释放掉空间,另外shrink_to_fit是在c++11中提出来的。 如果不支持C++11,可以使用创建一个临时的匿名容器再进行swap的方法来强制释放掉空间,因为交换之后,临时的匿名容器会立即被析构,而原来的容器则等于匿名容器的大小,也就是0)

#include <iostream>
#include <vector>

using namespace std;
int main(){
    vector it;
    double a[100]
    for(int i=0; i<100; i++){
        a[i] = i;
    }
    cout << "数据项个数: " << it.size() << "容器占有空间为: " << it.capacity() << endl;
    for(int i=0;i<100;i++){
        it.push_back(a[i]);
    }
    cout << ""数据项个数:" << it.size() << "容器占有空间为: " << it.capacity() << endl;
    it.clear();
    cout << "clear之后数据项个数: " << it.size() << "clear之后容器占有空间为: " << it.capacity() << endl;
    it.shrink_to_fit(); //or vector().swap(it);
     cout << "swap之后数据项个数: " << it.size() << "swap之后容器占有空间为: " << it.capacity() << endl;
     return 0;
}

            154757_YKWy_2368952.png



转载于:https://my.oschina.net/u/2368952/blog/415918

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值