加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C++智能指针unique_ptr

发布时间:2020-12-15 04:51:07 所属栏目:百科 来源:网络整理
导读:C++11:unique_ptr、shared_ptr、weak_ptr,本节介绍一下unique_ptr 1.智能指针产生原因 众所周知,C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。然而,很多程序员在使用堆内存时都很头疼,因为一次不恰当的使用方法,

C++11:unique_ptr、shared_ptr、weak_ptr,本节介绍一下unique_ptr

1.智能指针产生原因

众所周知,C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。然而,很多程序员在使用堆内存时都很头疼,因为一次不恰当的使用方法,很容易造成堆内存泄露(忘记释放),二次释放,程序发生异常时内存泄露等问题等。所以C++引入了智能指针,使用使用智能指针能更好的管理堆内存。

2.理解智能指针原理

1)智能指针是利用了一种叫做RAII技术对普通的指针进行封装,这使得智能指针实质是一个对象,行为表现的却像一个指针。

补充:RAII技术即资源分配及初始化,使用类来封装资源的分配和初始化,构造函数完成资源的分配和初始化,析构函数完成资源的清理,可以保证正确的初始化和资源释放。

2)智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放。智能指针的作用是防止忘记调用delete释放内存和程序异常的进入catch块忘记释放内存。另外指针的释放时机也是非常有考究的,多次释放同一个指针会造成程序崩溃,这些都可以通过智能指针来解决。千万不要用一块非new分配的动态内存去初始化一个智能指针,因为自行释放非堆地址很有可能出现问题。

3)智能指针还有一个作用是把值语义转换成引用语义。

C++和Java有一处最大的区别在于语义不同,在Java里面,下列代码:?

Student s1?= new Student ();

Student s2?= s1;

?这里其实只生成了一个对象,s1和s2仅仅是共享对象的引用而已。但在C++中不是这样的,

? Student s1;

? Student s2?= s1;

? 这里却是就是生成了两个对象。

3.包含头文件

C++98版的auto_ptr和C++11版的unique_ptr、shared_ptr、weak_ptr,都包含在头文件中,隶属于std命名空间中。

4.unique_ptr

unique_ptr持有对对象的独有权——两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作。但支持通过std::move转移内部指针所有权。

unique_ptr的成员函数:

1)get 获得内部对象的指针,由于已经重载了()方法,因此和直接使用对象是一样的.如 unique_ptr sp(new int(1)); sp 与 sp.get()是等价的;


2)release 放弃内部对象的所有权,将内部指针置为空,返回所内部对象的指针,此指针需要手动释放;


3)reset 销毁内部对象并接受新的对象的所有权(如果使用缺省参数的话,也就是没有任何对象的所有权,此时仅将内部对象释放,并置为空);

unique_ptr up1(new int); // ok

up1 = nullptr; //显式销毁所指对象,同时智能指针变为空指针。与u_s2.reset()等价

4)swap 交换两个unique_ptr对象(即交换所拥有的对象);

unique_ptr的用法:

1)unique_ptr对象不能进行拷贝和赋值操作,只能进行移动操作

unique_ptr up1(new int); // ok

unique_ptr up2 = up1; // 编译错误

unique_ptr up3(up1); // 编译错误

unique_ptr up4 = move(up1); // ok,up1变成空指针

查看拷贝构造和赋值源码,可以看到它们都被标记为已删除的函数了,在编译上面的代码时,会报编译错误:

unique_ptr(const _Myt&) = delete;

_Myt& operator=(const _Myt&) = delete;

当然,有些博主解释为,它们被设成了不可访问的私有函数。?

虽然 unique_ptr 不支持拷贝和赋值,但是可以调用 release 或 reset 将指针的所有权从一个(非 const) unique_ptr 转移到另一个。

std::unique_ptr up1(new int(1));

std::unique_ptr up2(up1.release()); // up1 放弃内部对象的所有权,将内部指针置为空

std::unique_ptr up3(new int(2));

up3.reset(up2.release()); //up3销毁内部对象,并接受新的对象的所有权

2)源unique_ptr是临时右值时,编译器允许将源unique_ptr临时右值赋给另一个unique_ptr对象

// 可以进行移动构造

template

std::unique_ptr Clone(const Ty& obj)

{

std::unique_ptr temp = std::unique_ptr(new Ty(obj)); // 编译器允许,源右值对象是临时右值

return temp; // 对象的所有权被传递出Clone()

}

unique_ptr pu1 = Clone(5);// 可以进行移动赋值,Clone函数返回值也是临时右值

unique_ptr pu2;

pu2 = pu1; // pu1不是临时右值,编译器不允许

unique_ptr pu3;

pu3 = unique_ptr(new int(2)); // 编译器允许,源右值对象是临右值

应该是编译器知道要临时右值的unique_ptr对象即将被销毁,因此执行一种特殊的"拷贝"。

3)两个unique_ptr不能指向一个对象

int *iPtr = new int(0);

std::unique_ptr up1(iPtr);

std::unique_ptr up2(iPtr);// 编译可以通过,但运行时发生错误

up2和up1都指向了iPtr,将来iPtr会被释放两次,造成错误。

4)unique_ptr支持管理动态数组

因为unique_ptr有unique_ptr重载版本,销毁动态对象时调用delete[]

unique_ptr p (new int[3]{1,2,3});

p[0] = 0;// 重载了operator[]

5)容器

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读