一、内置指针的初始化与赋值
vector<int>* q; //定义一个指针q,其指向的对象为vector<int>类型
指针初始化时,“=”的右操作数必须为内存中数据的地址,不可以是变量,也不可以直接用整型地址值(但是int*p=0;除外,该语句表示指针为空)。
int i = 3; int* p = &i; //正确, p被初始化,p指向的对象是整数3
int x, *p = &x; *p = 3; //将p所指向的对象的值赋值为3,即将x变成了3
int *p; *p = 3; //将p所指向的对象的值赋值为3,但是对象的地址未知(可以用很多地址里面的值为3),所以此时p仍属于未初始化
二、智能指针
shared_ptr<string> p; //定义了一个对象为string的智能指针p if (p) // 如果p指向一个对象,则返回true if( p-> empty()) //如果p指向的string对象为空,则返回true
(1) 每个shared_ptr都有一个相关联的计数器,成为引用计数。一旦引用计数变为0,它就会自动释放自己所管理的对象。
引用计数递增的情形:
1、用一个shared_ptr初始化另一个shared_ptr。
2、将一个shared_ptr作为参数传递给一个函数的形参。
3、将一个shared_ptr作为函数的返回值。
引用计数递减的情形:
1、给一个shared_ptr赋了一个新值。
2、一个局部的shared_ptr离开了其作用域(注意此时只是引用计数会递减,但不一定减为0,所以此时内存不一定被释放!)
(2)初始化
new返回的是一个指向该对象的内置指针!(不是智能指针)
int *p1 = new int ; //p1指向一个默认初始化的int型对象,*p1的值未定义
int *p2 = new int (); //p2指向一个值初始化的int型对象,即*p2 = 0
vector<int>* pv = new vector<int>{1,2,3,4,5} //pv指向一个元素为{1,2,3,4,5}的vector<int>型对象
//对于定义了自己的构造函数的类类型(例如string)来说,不管采用默认初始化还是值初始化,对象都会通过默认构造函数来初始化。
string *ps1 = new string; //默认初始化为空string
string *ps2 = new string(); //值初始化为空string
shared_ptr<int> p3 = make_shared<int>(); //p3指向一个值初始化的int型对象,即*p3 = 0
shared_ptr<int> p4 = make_shared<int>(42); //p4指向一个值为42的int型对象,即*p4 = 42
share_ptr<vector<int>>
不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式
shared_ptr<int> p = new int (1024); //错误!必须使用直接初始化形式
shared_ptr<int> p(new int (1024)); //正确。使用了直接初始化的形式
shared_ptr<vector<int>> pv(new vector<int>{1,2,3}); //pv指向一个元素为{1,2,3}的vector<int>型对象
(3)智能指针与普通内置指针的相互转换
转换前后一定要主要内存是否被释放的问题! 智能指针转换为普通指针: shared_ptr<int> p(new int (42)); int *q = p.get(); //令普通指针q指向智能指针p所指向的对象 普通指针转换为智能指针: int *q = new int(42); shared_ptr<int> p; p.reset(q); //令智能指针p指向普通指针q所指向的对象
p.reset(); //若p是唯一指向其对象的shared_ptr,reset会释放此对象