第12章 动态内存

简介: 第12章 动态内存

第12章 动态内存


动态内存的对象的生存期与它们在哪里创建是无关的,只有当显式地被释放时,这些对象才会销毁。


为了更安全地使用动态对象,标准库定义了两个智能指针类型来管理动态分配的对象。

当一个对象应该被释放时,指向它的智能指针可以确保自动地释放它。


静态内存用来保存局部static对象、类static数据成员以及定义在任何函数体之外的变量。


栈内存用来保存定义在函数体内的非static对象。


分配在静态或栈内存中的对象由编译器自动创建和销毁。


static对象在使用之前分配,在程序结束时销毁。


12.1 动态内存与智能指针


new在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化;


delete接受一个动态对象的指针,销毁该对象,并释放与之关联的内存


为了更容易地使用动态内存,新的标准库提供了两种智能指针类型来管理动态对象。


shared_ptr允许多个指针指向同一个对象


unique_ptr则“独占”所指向的对象


标准库还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。


三种类型都定义在memory头文件中


12.1.1 shared_ptr类



make_shared函数


shared_ptr<int> p3 = make_shared<int>(42);  //指向一个值为42的int的shared_ptr
shared_ptr<string> p4 = make_shared<string>(10, '9');
shared_ptr<int> p5 = make_shared<int>();


shared_ptr的拷贝和赋值


auto p = make_shared<int>(42);
auto p(q); //p和q指向相同对象,此对象有两个引用者


auto r = make_shared<int>(42);
r = q;
//给r赋值,令它指向另一个地址
//递增q指向的对象的引用计数
//递减r原来指向的对象的引用计数
//r原来指向的对象已没有引用者,会自动释放


12.1.2 直接管理内存


string *ps = new string;   //初始化为空string
int *pi = new int;         //pi指向一个未初始化的int


int *pi = new(1024);
int *ps = new string(10, '9');
vector<int> *pv = new vector<int>{0,1,2,3,4,5,6,7,8,9};


string *ps1 = new string;
string *ps2 = new string();
int *pi1 = new int;    //默认初始化 *pi1的值未定义
int *pi2 = new int();  //值初始化为0 *pi2为0


auto p1 = new auto(obj);
auto p2 = new auto{a,b,c};  //错误


const int *pci = new const int(1024);
const string *pcs = new const string;


传递给delete的指针必须指向动态分配的内存,或者是一个空指针


const对象的值不能被改变,但它本身是可以被销毁的


const int *pci = new const int(1024);
delete pci;


int *p(new int(42));
auto q = p;  //pq指向相同的内存
delete p;  //p和q均变为无效
p = nullptr;


12.1.3 shared_ptr和new结合使用


shared_ptr<double> p1;
shared_ptr<int> p2(new int(42));


我们不能将一个内置指针隐式转换为一个智能指针


shared_ptr<int> p1 = new int(1024);  //错误:必须使用直接初始化形式
shared_ptr<int> p2(new int(1024));   //正确:使用了直接初始化


shared_ptr<int> clone(int p){
    return new int(p);   //错误:隐式转换
}
shared_ptr<int> clone(int p){
    return shared_ptr<int>(new int(p));  //正确:显式
}




12.2 动态数组


int *p = new int[42];


初始化动态分配对象的数组


int *pia = new int[10];            //10个未初始化的int
int *pia2 = new int[10]();         //10个值初始化为0的int
string *psa = new  string[10];     //10个空string
string *psa2 = new string[10]();   //10个空string


初始化器初始化:


int *pia3 = new int[10]{0,1,2,3,4,5,6,7,8,9};
string *psa3 = new string[10]{"a", "an", "the"};  //初始化前几个


释放动态数组


delete [] pa;   //pa必须指向一个动态分配的数组或为空


typedef int arrT[42];   //arrT是42个int的数组的类型别名
int *p = new arrT;      //分配一个42个int的数组,p指向第一个元素
delete [] p;   //方括号是必须的,


空悬指针


在delete之后,指针就变成了空悬指针。即指向一块曾经保存数据对象但现在已经无效的内存的指针。


可以在delete之后将nullptr赋予指针,这样就清楚地指出指针不指向任何对象。


12.2.2 allocator类



allocator分配未构造的内存


当我们用完对象后,必须对每个构造的元素调用destroy来销毁它们。



//分配比vi中元素所占用空间大一倍的动态内存
auto p = alloc.allocate(vi.size() * 2);
//通过拷贝vi中的元素来构造从p开始的元素
auto q = uninitialized_copy(vi.begin(), vi.end(), p);
//将剩余元素初始化为42
uninitialized_fill_n(q. vi.size(), 42);
目录
相关文章
|
7月前
|
编译器 C++
C/C++动态内存开辟(详解)
C/C++动态内存开辟(详解)
动态内存管理之realloc函数
动态内存管理之realloc函数
|
编译器 C语言
动态内存管理之malloc函数
动态内存管理之malloc函数
|
2月前
|
程序员 C语言
动态内存分配
【10月更文挑战第10天】
41 5
|
6月前
|
C语言
动态内存
【6月更文挑战第16天】
38 10
|
6月前
|
编译器 C语言
动态内存开辟(上)
动态内存开辟(上)
29 0
|
6月前
|
C语言
动态内存开辟(下)
动态内存开辟(下)
25 0
|
7月前
|
安全 C++ 容器
C++ 动态内存
C++ 动态内存
37 0
|
C语言
【动态内存管理】动态内存函数
【动态内存管理】动态内存函数