三种智能指针

智能指针

new和delete

1:new初始化
  • new未初始化值
c++ 复制代码
    int *p = new int;//p值未定义
    string *str = new string;//为空串,调用string默认构造函数
  • new 初始化值
c++ 复制代码
    int *p = new int(100);
    string *str = new string(6,'a');//aaaaaa
  • vector类型指针
c++ 复制代码
 vector<int> *p = new vector<int>{1, 3, 5, 7, 9};
    vector<int> mm{9, 8, 7, 6};
    vector<int> *nn = &mm;
    for (int i = 0; i < p->size();i++){
        cout << p->at(i) << ",";
    }
    for (int i = 0; i < nn->size();i++){
        cout << nn->at(i) << ",";
    }

注意:

c++ 复制代码
vector<int> *p = new vector<int>{1, 3, 5, 7, 9};
//p->size()与(*p).size()等价
//p->at(i)等价于(*p).at(i)等价于(*p)[i]
 for (int i = 0; i < p->size();i++){
        cout << (*p).at(i)<< ",";
 }
2:值初始化
c++ 复制代码
    string *mystr = new string();//空字符串
    int *p = new int();//赋值0

如果是类的值初始化,调用类的构造函数

c++ 复制代码
class A{
public:
    A(){
        cout << "call()" << endl;
    }
};
int main(){
    A *a = new A();
    return 0;
}

运行结果:call()

不加()效果一样: A *a = new A;

  • new和auto的配合使用
c++ 复制代码
    string *s = new string(7, 'a');
    //这里s是指针,所以auto的类型是string*
    auto *mystr = new auto(s);
    //string **mystr = new string *(s);
    cout << (*mystr)->c_str() << endl;
    //cout << *(*mystr)<< endl;
  • const可以和new配合使用
c++ 复制代码
const int *p = new const int(200);
//const int *p = new int(200);---new后可以不加const

const修饰的p指针不可以改变 *p=200;是错的

3:delete

new和delete是配合使用的,delete用于回收new分配出的内存空间,而且delete只能使用一次去释放内放

注意:delele只能释放new分配的空间

c++ 复制代码
 int i = 100;
 int *p = &i;
 delete p;//报错:p指向的内存不是new出来的

多个指针指向同一块内存,没必要重复delete

c++ 复制代码
 int *p = new int(100);
 int *p2 = p;//p和p2指向同一块内存
 delete p;//输出*p2会出错
 delete p2;//没必要多次释放

总结
  1. new出来的必须delete,不然内存泄漏,会导致程序崩溃
  2. delete后的内存不能再次使用
  3. 不要对同一个内存多次delete
c++ 复制代码
 int* p = new int(9);
 delete p;
 *p = 300;//释放之后使用会出错,最好置成NULL
 //p=NULL;
 cout << *p << endl;
  • new和delete都是运算符,不是函数。

  • new和delete相比于malloc和free可以干更多事

    ---在堆上分配一个对象时,new和delete会自动调用类的构造和析构函数

    也就是存在初始化能力,malloc和free没有这个能力

😄A a; sizeof(a);---------空类的对象也占有一个字节,因为空类对象有地址,至少在内存占一个字节


4:operator new()和operator delete()

new运算符会分配内存调用构造函数,这里分配内存就是调用operator new()函数

delete运算符会调用析构函数然后释放内存operator delete()(顺序和new相反)

5:申请和释放数组
c++ 复制代码
 int *p = new int[2];//中括号是数组,分配两个数据

class A{
public:
   A(){}
};
int main(){
    A *pa = new A[2]();
    delete[] pa;//别忘【】
}

内置类型,比如:int,double,delete时候不需要调用析构函数

int *pa=new int[4];

delete pa;delete[] pa;是一样的,因为int是内置类型,不需要析构函数。


如果是自定义类对象,用new分配了一个对象数组:A *a=new A[3] ();

这时候如果类存在自定义析构函数,必须用delete[]释放

注意:new的不是数组,也不要用delete[]。

智能指针总述

前提:new和delete非常容易出错

比如忘记delete

c++ 复制代码
int *p=new int;
if(con){
    return;//提前返回
}
delete p;

或者提前释放

比如:delete后的指针依然被继续使用

裸指针是直接new出来的指针

智能指针 :对裸指针进行了包装,最突出的优点就是自动释放new的对象内存

四种智能指针:

c++ 复制代码
    auto_ptr;//完全被unique_ptr取代,被摒弃
    /*新标准c++11的三种智能指针都是类模板,可以给它们赋值new获得的地址*/
    unique_ptr;----独占指针,同一时间内只有一个指针指向该对象。但是可以把所有权移交。
    shared_ptr;----多个指针指向同一对象,最后一个指针被销毁,对象才被释放
    weak_ptr;----辅助shared_ptr使用

1:shared_ptr

共享所有权,不是被一个shared_ptr拥有,而是被多个shared_ptr相互协作,有额外开销。

工作原理:引用计数,每个shared_ptr的拷贝都指向相同的内存。

​ 所以最后一个指向该shared_ptr指针不再指向该对象时,这个shared_ptr才会去析构所指向的内存。

c++ 复制代码
    shared_ptr<int> p1(new int(100));
    shared_ptr<int> p2 = new int(200);//×,只能显示赋初值()
//----------------------------------------------------------
shared_ptr<int> make(int val){
    return shared_ptr<int>(new int(val));
}
shared_ptr<int> p3 = make(300);

智能指针和裸指针不要穿插使用

c++ 复制代码
 int *p = new int;
 shared_ptr<int> ptr(p);//不要这么使用
 shared_ptr<int> ptr(new int);//可以
make_shared()创建对象

标准库里的函数模板,能够高效的分配和使用share_ptr,别忘了匹配参数<类型>

但是make_shared()不能指定删除器

c++ 复制代码
 shared_ptr<int> p = make_shared<int>(100);
 shared_ptr<string> s = make_shared<string>(10,'a');
shared_ptr的引用参数

当进行赋值或拷贝时,每个shared_ptr都会有一个引用参数,用来记录有多少个指向同一内存的其他shared_ptr对象

引用参数其实就是一个计数器,用来记录当前指向同一个内存的shared_ptr的个数

1.引用计数的增加
c++ 复制代码
 auto p1 = make_shared<int>(100);//创建一个shared_ptr,p1引用计数为1
 shared_ptr<int> p2(p1);//用p1给p2拷贝,p1和p2此时引用计数为2
 auto p3 = p2;//p2给p3赋值,p1,p2,p3引用计数为3

函数非引用传参,在函数体内引用参数+1

c++ 复制代码
void myfun(shared_ptr<int> tmp) {
 return;
}
int main() {
 auto p1 = make_shared<int>(100);//创建一个shared_ptr,p1引用计数为1
 myfun(p1);
}

如果传的是引用,那么引用参数不增加

c++ 复制代码
void myfun(shared_ptr<int>& tmp) {//引用
    return;
}
int main() {
    auto p1 = make_shared<int>(100);//创建一个shared_ptr,p1引用计数为1
    myfun(p1);
}
  • 接受make_shared返回值,引用参数加1
c++ 复制代码
shared_ptr<int> getPtr(shared_ptr<int>& p) {
 return p;
}
int main() {
 auto p1 = make_shared<int>(100);//创建一个shared_ptr,p1引用计数为1
 auto p2 = getPtr(p1);
 getPtr(p2);//临时对象没有参数接收,执行后引用参数不增加
}
2.引用计数的减少
  1. 局部的值传递shared_ptr离开作用域

  2. shared_ptr指向了新对象

c++ 复制代码
auto p1 = make_shared<int>(100);
auto p2 = getPtr(p1);
auto p3 = p2;
/*指针指向新对象,引用计数-1*/
p1 = make_shared<int>(33);
  1. 当一个shared_ptr的引用计数从1变为0,智能指针自动释放
c++ 复制代码
 auto p1 = make_shared<int>(20);
 auto p2 = make_shared<int>(30);
 p1 = p2;//p1和p2引用计数为2,原来p1的内存被释放
shared_ptr指针常用操作
  • use_count()---返回指向某个对象的引用计数
c++ 复制代码
shared_ptr<string> ptr(new string(5, 'a'));
int cnt = ptr.use_count();//1
shared_ptr<string> p2(ptr);
cout << ptr.use_count();//2
shared_ptr<string> p3 = p2;
cout << ptr.use_count();//3
  • unique()----该智能指针是否独占对象

为空也不行,必须use_count()为1

c++ 复制代码
  shared_ptr<string> ptr(new string(5, 'a'));
  cout << ptr.unique() << endl;//真
  shared_ptr<string> p2(ptr);
  cout << p2.unique() << endl;//假
  • reset()---复位
    1. 不带参数,把唯一指向该对象的指针的内存释放,并把指针置空。
    2. 不带参数,但是多个指向该对象,把引用计数-1,并把指针置空。
c++ 复制代码
   shared_ptr<string> ptr(new string(5, 'a'));
   shared_ptr<string> p2(ptr);
   p2.reset();
   if (p2 == nullptr) {
       cout << "p2 is NULL" << endl;
   }
   cout << ptr.use_count() << endl;
  1. 带参数,把唯一指向该对象的指针的内存释放,并把指针指向新对象。
  2. 带参数,但是多个指向该对象,把引用计数-1,并把指针指向新对象。

shared_ptr<int> p1(new int(100));

p1.reset(new int(200));`

c++ 复制代码
  shared_ptr<int> p1(new int(100));
  auto p2(p1);
  p1.reset(new int(200));
  if (p1.unique()) {
      cout << "p1 is unique;" << endl;
  }
  if (p2.unique()) {
      cout << "p2 is unique;" << endl;
  }

空指针也可以用reset()初始化

shared_ptr p1;***

p1.reset(new int(30));***

  • 解引用---获得指针指向的对象

用法同普通指针

c++ 复制代码
    shared_ptr<int> p1=make_shared<int>(99);
    cout << *p1 << endl;//99
    shared_ptr<string> p2 = make_shared<string>(5, 'a');
    cout << *p2 << endl;//aaaaa
  • get()---返回保存的指针,小心使用,如果释放了所指向对象,指针无效

说白了返回裸指针,这个函数目的就是某些第三方函数传参只能使用裸指针

c++ 复制代码
shared_ptr<int> p = make_shared<int>(99);
int* ptr = p.get();
cout << *ptr << endl;//99
//千万不能delete该裸指针
  • swap()----交换两个对象内容
c++ 复制代码
	shared_ptr<string> p1 = make_shared<string>("aaabbb");
	shared_ptr<string> p2(new string("cccddd"));
	swap(p1, p2);
	cout << *p1 <<","<< * p2 << endl;
	p1.swap(p2);
	cout << *p1 << "," << *p2 << endl;
  • =nullptr----置空
c++ 复制代码
	shared_ptr<string> p1 = make_shared<string>("aaabbb");
	shared_ptr<string> p2(p1);
	p1 = nullptr;
	//p1是空指针,p2指向aaabbb且引用计数为1
	if (!p1) {
		cout << "空指针" << endl;
	}
shared_ptr指定删除器(自定义删除)

在参数中指定删除器函数名即可,自己必须delele对象,不然内存泄漏。

注意make_shared这种方式不能指定删除器

可以用lambda表达式

c++ 复制代码
shared_ptr<int> p1(new int(100), [](int* p) {
	cout << "****" << endl;
	delete p;
});//加入参数
c++ 复制代码
//当引用计数为0,自动调用该函数
void myDelete(int* p) {
	cout << "call myDelete!" << endl;
	delete p;
}
int main() {
	shared_ptr<int> p1 (new int(100),myDelete);//加入参数
	auto p2(p1);
	p2.reset();
	p1 = nullptr;
}

用shared_ptr管理动态数组,只能自己释放

c++ 复制代码
shared_ptr<int> p1(new int[10], [](int* p) {
	delete[] p;
});//加入参数
c++ 复制代码
//shared_ptr<A> ptr(new A[5]);//系统释放异常。系统delete是ptr的裸指针。
shared_ptr<A> ptr(new A[5], [](A* p) {
	delete[] p;
});

可以用default_delete来释放,<>指定数组

c++ 复制代码
shared_ptr<A> ptr(new A[5], default_delete<A[]>());

在最开始加个[]就可以正常释放数组

c++ 复制代码
	shared_ptr<A[]>  ptr(new A[5]);
	shared_ptr<int[]> p(new int[3]{1,2,3});
	cout << p[2] << endl;//加了[]可以下标访问

函数模板来定义数组

c++ 复制代码
template<typename T>
shared_ptr<T> make_arr(size_t sz) {
	return shared_ptr<T>(new T[sz], default_delete<T[]>());
}
int main() {
	shared_ptr<int > p1= make_arr<int>(3);
	shared_ptr<string > p2 = make_arr<string>(4);
}

注意:就算两个shared_ptr指定了不同的删除器,只要指向的对象类型相同,这两个shared_ptr也是一个类型

类型相同就是可以用同一个容器装

c++ 复制代码
shared_ptr<int> p1(new int(100), f1);
shared_ptr<int> p2(new int(200), f2);
vector<shared_ptr<int>> vec{ p1,p2 };
c++ 复制代码
	auto f1 = [](int *p) {
		cout << "f1()" << endl;
		delete p;
	};
	auto f2 = [](int* p) {
		cout << "f2()" << endl;
		delete p;
	};
	shared_ptr<int> p1(new int(100), f1);
	shared_ptr<int> p2(new int(200), f2);
	p2 = p1;//p2指向其他,调用f2释放自己对象,p1的引用计数+1
	//最后执行结束前,p2和p1用f1释放

2:weak_ptr

weak_ptr用来辅助shared_ptr<进行工作

  • 强指针就是:shared_ptr
  • 弱指针就是:weak_ptr

weak_ptr也是一个类模板 构造的智能指针,weak_ptr指向一个由shared_ptr管理的对象

❗️❗️注意❗️❗️

  • weak_ptr这种智能指针不控制所指向的对象的生命周期

​ 如果shared_ptr和weak_ptr指向同一对象,或者说将weak_ptr绑定到shared_ptr上,并不会改变shared_ptr的引用计数。即:weak_ptr的构造和析构不能增加或减少所指向对象的引用计数。

弱引用weak_ptr是监视shared_ptr生命周期用的,weak_ptr不是一种独立的智能指针,不能用来操作所指向的资源。

注意:只有强引用才能影响对象的生命周期

c++ 复制代码
/*一般用一个shared_ptr来初始化weak_ptr*/
shared_ptr<int> ps = make_shared<int>(100);
weak_ptr<int> ps_w(ps);
//弱引用赋值给弱引用
weak_ptr<int> ps_w2 = ps_w;
lock()

因为weak_ptr指向的对象的声明周期可能结束了,所以weak_ptr使用对象前,必须判断对象是否存在

lock()就是检查weak_ptr指向的对象是否存在

  • 如果存在,lock()返回一个该对象的shared_ptr,此时引用计数+1
  • 如果不存在,lock()返回一个空的shared_ptr
c++ 复制代码
int main() {
	/*一般用一个shared_ptr来初始化weak_ptr*/
	shared_ptr<int> ps = make_shared<int>(100);
	weak_ptr<int> ps_w(ps);
	//pi接受ps_w指向对象的强引用
	auto pi = ps_w.lock();
	if (pi) {
		*pi = 99;//改变值
	}
	else {
		cout << "no duixiang!!" << endl;
	}
	cout << *ps << endl;//99,改变值成功
}
c++ 复制代码
int main() {
	/*一般用一个shared_ptr来初始化weak_ptr*/
	shared_ptr<int> ps = make_shared<int>(100);
	weak_ptr<int> ps_w(ps);
	//pi接受ps_w指向对象的强引用
	ps.reset();//减少一个强引用,此时指向的对象被释放
	auto pi = ps_w.lock();
	if (pi) {
		*pi = 99;//改变值
	}
	else {
		cout << "no duixiang!!" << endl;
	}
}

也就是weak_ptr可以判断指向对象存在性

use_count()

获取weak_ptr的强引用计数

c++ 复制代码
int main() {
	auto p1 = make_shared<int>(11);//p1是shared_ptr
	auto p2(p1);//p2是shared_ptr
	weak_ptr<int> pw(p1);
	cout << pw.use_count() << endl;//2
}
expired()

是否过期的意思,弱指针的use_count为0时候返回true。也就是判断指向对象的存在性

c++ 复制代码
int main() {
	auto p1 = make_shared<int>(11);//p1是shared_ptr
	auto p2(p1);//p2是shared_ptr
	weak_ptr<int> pw(p1);
	p1.reset();
	p2.reset();
	if (pw.expired()) {
		cout << "对象已经过期" << endl;
	}
}
reset()

将弱引用指针涉为空,弱引用计数-1

c++ 复制代码
int main() {
	auto p1 = make_shared<int>(11);//p1是shared_ptr
	auto p2(p1);//p2是shared_ptr
	weak_ptr<int> pw(p1);
	p1.reset();
	pw.reset();//执行后,p2指向对象没有弱引用
	cout << *p2 << endl;//11
}

综合使用

c++ 复制代码
int main() {
	auto p1 = make_shared<int>(100);
	weak_ptr<int> pw = p1;
	if (!pw.expired()) {//pw对象存在
		auto p2 = pw.lock();
		if (p2) {
			cout << p2.use_count() << endl;
		}
	}
	//p2离开了作用域,引用计数-1
	cout <<"***"<< p1.use_count() << endl;
}

运行结果:

2
***1

智能指针尺寸

c++ 复制代码
C++的一个指针占内存几个字节?
----在64位编译模式下,指针的占用内存大小是8字节
----在32位编译模式下,指针占用内存大小是4字节

智能指针大小是普通指针的两倍

c++ 复制代码
	int* p;
	shared_ptr<int> ps;
	weak_ptr<int> pw;
	cout << sizeof(p) << endl;
	cout << sizeof(ps) << endl;
	cout << sizeof(pw) << endl;

运行结果:

8

16

16

智能指针内部包含两个裸指针

  • 一个指针指向对象
  • 第二个指针指向控制块(一个很大的数据结构)
    • 控制块有:强引用计数,弱引用计数,其他数据比如自定义删除器

❗️其中❗️:

  • shared_ptr创建控制块,weak_ptr指向控制块

  • 这个控制块是第一个创建shared_ptr的对象创建

    make_share():一定可以创建出一个控制块

    裸指针可以创建一个控制块(但是不要用裸指针初始化多个)

❗️shared_ptr使用深入

利用函数创建shared_ptr

c++ 复制代码
//从函数中return shared_ptr
shared_ptr<int> create_ptr(int val){
	return make_shared<int>(val);
}
//利用对象来接shared_ptr,返回对象
shared_ptr<int> myPtr(int val){
	shared_ptr<int> tmp = create_ptr(val*2);
	//系统根据tmp这个局部变量产生一个临时变量往回返
	return tmp;
}
int main(){
	shared_ptr<int> p1 = create_ptr(100);
	shared_ptr<int> p2 = myPtr(200);
	cout << *p1 << "," << *p2 << endl;
}

shared_ptr使用陷阱

  1. 慎用裸指针
c++ 复制代码
void profun(shared_ptr<int> ptr){
	cout << ptr.use_count() << endl;
	return;
}
int main(){
	int *p = new int(11);
	shared_ptr<int> p2(p);
	//profun(p);--注意裸指针和智能指针不存在隐式转换
	profun(p2);
	*p = 300;
	//利用裸指针创建的智能指针后续值会变化
	cout << *p << "," << *p2 << endl;//300,300
}

而且利用裸指针创建的智能指针,后续值会随着裸指针变化。所以最好后续不要用裸指针

c++ 复制代码
void profun(shared_ptr<int> ptr){
	cout << ptr.use_count() << endl;
	return;
}
int main(){
	int *p1 = new int(11);
	//这样临时对象传入函数,引用计数不+1,所以return后内存释放
	profun(shared_ptr<int>(p1));
	cout << *p1 << endl;
	shared_ptr<int> p2(new int(100));
	//但是直接创建智能指针,传入函数引用计数+1
	profun(p2);
}

发现p1内存异常,因为临时对象传入profun()不会增加引用计数,所以函数运行结束内存会释放

但是直接传入shared_ptr,引用计数会增加,不会影响主程序的p2

不要用裸指针初始化多个shared_ptr

c++ 复制代码
	int *p1 = new int(11);
	shared_ptr<int> p2(p1);
	shared_ptr<int> p3(p1);
	//1,1
	cout << p2.use_count() << "," << p3.use_count() << endl;

发现p2,p3不会增加引用计数,所以释放时候会delete2次,会异常

  1. 慎用get()返回的指针

❗️get返回的是智能指针中的裸指针,这个指针不能delete

c++ 复制代码
	shared_ptr<int> p(new int(100));
	int* pm = p.get();
	//pm虽然得到了p的指针,但是内存管理还是归智能指针
	//裸指针不可以释放内存
	delete pm;

❗️不能将其他智能指针绑定到get的裸指针

这就是不增加引用计数,会delete多次

c++ 复制代码
	shared_ptr<int> p(new int(100));
	int* pm = p.get();
	shared_ptr<int> q(pm);
	//都是1,因为这样和绑定裸指针一样,不增加引用计数
	cout << p.use_count() << "," << q.use_count();

get的裸指针不能delete而且也不用该指针赋值或初始化

  • 不要把类指针this作为shared_ptr返回,改用enable_shared_from_this
c++ 复制代码
class CT {
public:
	shared_ptr<CT> getself() {
		return shared_ptr<CT>(this);
	}
};
int main(){
	shared_ptr<CT> pt(new CT);
	shared_ptr<CT> p2 = pt;
}

这样p2,pt的引用计数都是2

c++ 复制代码
class CT {
public:
	shared_ptr<CT> getself() {
		return shared_ptr<CT>(this);
	}
};
int main(){
	shared_ptr<CT> pt(new CT);
	//说白了this也是类的裸指针,初始化了多个对象
	//这里引用计数不增加
	shared_ptr<CT> p2 = pt->getself();
	cout << p2.use_count() << endl;
}

它们指向同一内存但是不是同样的内存块

enable_shared_fron_this是类模板

c++ 复制代码
//公有继承了enable_shared_from_this模板
class CT :public enable_shared_from_this<CT>{
public:
	shared_ptr<CT> getself() {
		return shared_from_this();//模板中的方法
	}
};
int main(){
	shared_ptr<CT> pt(new CT);
	shared_ptr<CT> p2 = pt->getself();
	cout << p2.use_count() << endl;
}

这样就可以增加引用计数了
原理就是:enable_shared_from_this里面有一个弱指针,这个弱指针指向this,然后每次创建新对象就会调用lock(),保证了shared_ptr的引用计数增加
移动语义

c++ 复制代码
	shared_ptr<int> p1(new int(100));//p1地址:0x000001f36d6d0850
	//这样p1为空,p2指向了内存
	shared_ptr<int> p2(move(p1));//p2地址:0x000001f36d6d0850
	/*move函数:让p2接管了p1的地址,然后把p1置空*/
	shared_ptr<int> p3;
	p3 = move(p2);//同样p3接管p2,p2置空
	if (!p2) {
		cout << "p2 id NULL" << endl;
	}

shared_ptr还有分配器,涉及内存分配。

c++ 复制代码
//使用make_shared更高效
shared_ptr<string> p1(new string("good for you"));//分配两次内存
shared_ptr<string> p2=make_shared("good for you");//释放一次内存

3:unique_ptr

unique_ptr是独占对象,所以同一时间只能由一个unique_ptr指向对象

unique_ptr被销毁的时候,它所指向的对象也会被销毁

初始化
c++ 复制代码
int main() {
    unique_ptr<int> p;
    if (p == nullptr) {
        cout << "p是空指针" << endl;
    }
    unique_ptr<int> p2(new int(100));
    //c++14才有make_unique(),这个创建不能指定删除器
    unique_ptr<int> p3 = make_unique<int>(200);
    cout << *p2 << "," << *p3 << endl;
}
unique_ptr不支持的操作

核心就是unique_ptr独占内存

移动语义
release()

将智能指针和对象联系切断,放弃指针的控制权。返回裸指针,然后把智能指针置空

返回的裸指针可以delete也可以给其他指针赋值

c++ 复制代码
	unique_ptr<string> p1 = make_unique<string>("good luck");
	//p2接管p1,p1置空
	unique_ptr<string> p2(p1.release());
	if (p1 == nullptr) {
		cout << "p1被置空" << endl;
	}
	p2.release();
	//如果没有delete那么内存泄露

正确释放

c++ 复制代码
	string* tmp=p2.release();
	delete tmp;
reset()
  • reset()无参数----释放智能指针指向的对象并将智能指针置空
  • reset()带参数----释放智能指针指向的对象并将智能指针指向新对象
c++ 复制代码
	unique_ptr<string> p1 = make_unique<string>("good luck");
	unique_ptr<string> p2 = make_unique<string>("hello world");
	p1.reset();
	if (p1 == nullptr) {
		cout << "p1被置空" << endl;
	}
	p1.reset(p2.release());//p2release后被置空,reset释放p1指向的内存,让p1指向p2的裸指针
	if (p1) {
		cout << *p1<< endl;
	}
c++ 复制代码
	unique_ptr<string> p1 = make_unique<string>("good luck");
	p1.reset(new string("hello world"));
	cout << *p1 << endl;//hello world
c++ 复制代码
	unique_ptr<string> p1 = make_unique<string>("good luck");
	//释放p1指向对象的内存
	//并将p1置空
	p1 = nullptr;
指向数组

一般不用,因为容器更好用

get()

返回智能指针的裸指针,但是要注意不要提前释放

c++ 复制代码
	unique_ptr<string> up = make_unique<string>("hello,world");
	string* tmp = up.get();
	cout << *tmp << endl;

一般是作为库函数的函数接口参数

转换成shared_ptr
c++ 复制代码
auto myfun() {
	return unique_ptr<string>(new string("hello, world"));
}
int main() {
	//注意:unique_ptr没有控制块
	//p在这里创建
	shared_ptr<string> p = myfun();
	unique_ptr<string> mm(new string("good,luck"));
	shared_ptr<string> nn = move(mm);
}
相关推荐
A懿轩A23 分钟前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
机器视觉知识推荐、就业指导28 分钟前
C++设计模式:享元模式 (附文字处理系统中的字符对象案例)
c++
半盏茶香28 分钟前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
Ronin3051 小时前
11.vector的介绍及模拟实现
开发语言·c++
✿ ༺ ོIT技术༻1 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
字节高级特工1 小时前
【C++】深入剖析默认成员函数3:拷贝构造函数
c语言·c++
唐诺8 小时前
几种广泛使用的 C++ 编译器
c++·编译器
冷眼看人间恩怨9 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
红龙创客9 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin9 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin