C++基础知识面试必备、复习细节 (7) (关联容器、动态内存)
pair类型
-
pair保存两个数据成员,通常用来存储具有一定关系的二元组
-
pair<int,string> t; //保存一个int和一个string pair<int,vector<int>> m; //保存一个int和一个vector<int> t=make_pair(i,str); //t的值为 <i,str> cout<<t.first<<" "<<t.second<<endl; //输出pair
-
自己常在二维矩阵问题中使用pair<int,int> 用来表示坐标
关联容器
关联容器类型 | 特点 |
---|---|
map | 关联数组:关键字–值的映射 map<int,string> t : t是一个int到string的映射。 可以通过迭代器进行遍历,map中元素为pair类型,first表示键,second表示值 实现是红黑树实现 |
set | 集合(元素不重复) set<int> t : t是一个保存int的集合,常用find()查找元素是否在set中 可以通过迭代器进行遍历 实现是红黑树实现 |
multimap | 关键字可重复的map |
multiset | 关键字可重复的set |
unordered_map | 由哈希函数实现的map |
unordered_set | 由哈希函数实现的set |
-
向map中添加元素,可以直接通过 map[key]=val; 实现建立一个key到val的映射关系
-
常用的一个函数 find(k),如果找到则返回第一个关键字为k的元素,否则返回尾之后的迭代器 即end()
-
map内部实现了一个红黑树,红黑树具有自动排序的功能,因此map内部的所有元素都是有序的;
unordered_map内部实现了一个哈希表,其元素的排列顺序是无序的
内存分布
- 静态内存:保存局部static对象、类static数据成员以及定义在函数外的变量。在编译阶段自动创建,程序结束才销毁。
- 栈内存:用来保存定义在函数内的非static对象,自上而下生长。只有在定义的程序块运行时才存在
- 堆内存:程序员自己动态管理,自下而上生长,用来存储动态分配的对象。
动态内存
-
在c++中通过new和delete管理动态内存。new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象初始化; delete接收一个动态对象的指针并销毁该对象,释放与之关联的内存。
-
忘记释放内存将导致内存泄漏;释放一个还有别的指针在引用的内存将导致产生非法内存的指针
空悬指针:指针指向的对象空间已经被释放 野指针:没用初始化的指针
-
malloc/free 和new/delete的区别
malloc只分配指定大小的堆内存空间,而new可以根据对象类型分配合适的堆内存空间。free释放对应的堆内存空间,delete,先执行对象的析构函数,在释放对象所占空间。malloc分配时的大小是人为计算的,返回类型是void*,使用时需要类型转换,new在分配时,编译器能够根据对象类型自动计算出大小,返回类型是指向对象类型的指针。new调用构造函数构造对象,而malloc不能;delete将调用析构函数析构对象,而free不能
-
动态数组:
int *pia=new int[size]; //pia指向第一个int for(int* q=pia;q!=pia+size;++q) //遍历动态数组 /* dosometing() */ delete [] pia;
释放动态数组时通过 delete [] 释放
智能指针
-
c++11提供了智能指针来管理动态对象。智能指针可以自动释放所指向对象
-
shared_ptr类:
#include<memory> share_ptr<string> p1; //shared_ptr,指向string make_shared<T> (args); //返回一个shared_ptr,指向一个动态分配的类型为T的对象,使用args初始化 auto p1=make_shared<int> (5); //指向一个值为5的int的shared_ptr shared_ptr<int> p(new int(5));
shared_ptr支持多个指针指向同一区域。当拷贝或赋值时,shared_ptr会动态保存引用计数,当拷贝或赋值时会增加,当修改值或者销毁时会减少。计数器变为0时释放自己所管理的对象。
当shared_ptr销毁时当调用其析构函数,递减其引用检查引用计数是否为0,如果为0则将所指向的对象也销毁,并释放占用的内存
注意避免循环引用,shared_ptr的一个最大的陷阱是循环引用(当两个对象相互使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏)
-
unique_ptr类:
unique_ptr:在某个时刻只能有一个unique_ptr指向一个给定对象,不允许共享。当unique_ptr销毁时,其指向的对象也被销毁 unique_ptr不支持拷贝和赋值构造 有效避免资源泄露(例如“以new创建对象后因为发生异常而忘记调用delete”) 不共享它的指针
unique_ptr<int> p1; unique_ptr<int> p2(new int(42));
-
weak_ptr类:
不增加计数,为了解决shared_ptr存在相互引用的问题,确保能够正确析构。是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象。最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。weak_ptr可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加
auto p=make_shared<int>(10); weak_ptr<int> wp(p); //wp弱共享p,p引用计数未改变