建网站 3年服务器,磁力搜索引擎哪个好,怎么建设企业网站,代搭建网站普通指针的不足 new和new[]的内存需要用delete和deletel]释放。 程序员的主观失误#xff0c;忘了或漏了释放。 程序员也不确定何时释放。
普通指针的释放 类内的指针#xff0c;在析构函数中释放。 C内置数据类型#xff0c;如何释放? new出来的类#xff0c;本身如… 普通指针的不足 new和new[]的内存需要用delete和deletel]释放。 程序员的主观失误忘了或漏了释放。 程序员也不确定何时释放。
普通指针的释放 类内的指针在析构函数中释放。 C内置数据类型如何释放? new出来的类本身如何释放?
C11新增三个智能指针类型 unique_ptr shared_ptr weak_ptr
一、智能指针unique_ptr
unique_ptr独享它指向的对象也就是说同时只有一个unique_ptr指向同一个对象当这个unique_ptr被销毁时指向的对象也随即被销毁。unique_ptr是一个类它的内部维护一个内置的指针他的析构函数中会delete内置指针。
包含头文件#include memory
template typename T, typename D default_deleteT
class unique_ptr
{
public:explicit unique_ptr(pointer p) noexcept; // 不可用于转换函数。~unique_ptr() noexcept; T operator*() const; // 重载*操作符。T* operator-() const noexcept; // 重载-操作符。unique_ptr(const unique_ptr ) delete; // 禁用拷贝构造函数。unique_ptr operator(const unique_ptr ) delete; // 禁用赋值函数。unique_ptr(unique_ptr ) noexcept; // 右值引用。unique_ptr operator(unique_ptr ) noexcept; // 右值引用。// ...
private:pointer ptr; // 内置的指针。
};
explicit 关键字
加上explicit后让构造函数不可以被用作转换函数使用。以下调用非法
AA *p new AA(xianwu); //普通指针
unique_ptrAA pu2 p;
1、基本用法
1初始化
方法一推荐
unique_ptrAA p0(new AA(西施)); // 分配内存并初始化。
方法二
unique_ptrAA p0 make_uniqueAA(西施); // C14标准。
方法三不推荐原始指针出现如果构造给多个unique_ptr会造成多次释放内存操作野指针存在风险。
AA* p new AA(西施);unique_ptrAA p0(p); // 用已存在的地址初始化。
2使用方法
智能指针重载了*和-操作符可以像使用指针一样使用unique_ptr。不支持普通的拷贝和赋值。
AA* p new AA(西施);
unique_ptrAA pu2 p; // 错误不能把普通指针直接赋给智能指针。
unique_ptrAA pu3 new AA(西施); // 错误不能把普通指针直接赋给智能指针。
unique_ptrAA pu2 pu1; // 错误不能用其它unique_ptr拷贝构造。
unique_ptrAA pu3;
pu3 pu1; // 错误不能用对unique_ptr进行赋值。
不要用同一个裸指针初始化多个unique_ptr对象。get()方法返回裸指针。不要用unique_ptr管理不是new分配的内存。
3用于函数的参数 传引用不能传值因为unique_ptr没有拷贝构造函数。 裸指针。
4不支持指针的运算、-、、--
2、更多技巧 面试就爱考点技巧之类的
1将一个unique_ptr赋给另一个时如果源unique_ptr是一个临时右值编译器允许这样做如果源unique_ptr将存在一段时间编译器禁止这样做。一般用于函数的返回值。
unique_ptrAA p0;
p0 unique_ptrAA(new AA (西瓜));
2用nullptr给unique_ptr赋值将释放对象空的unique_ptrnullptr。
3release()释放对原始指针的控制权将unique_ptr置为空返回裸指针。可用于把unique_ptr传递给子函数子函数将负责释放对象
4std::move()可以转移对原始指针的控制权。可用于把unique_ptr传递给子函数子函数形参也是unique_ptr
5reset()释放对象。
void reset(T * _ptr (T *) nullptr);pp.reset(); // 释放pp对象指向的资源对象。
pp.reset(nullptr); // 释放pp对象指向的资源对象
pp.reset(new AA(bbb)); // 释放pp指向的资源对象同时指向新的对象。
6swap()交换两个unique_ptr的控制权。
void swap(unique_ptrT _Right);
7unique_ptr也可像普通指针那样当指向一个类继承体系的基类对象时也具有多态性质如同使用裸指针管理基类对象和派生类对象那样。
8unique_ptr不是绝对安全如果程序中调用exit()退出全局的unique_ptr可以自动释放但局部的unique_ptr无法释放。
9unique_ptr提供了支持数组的具体化版本。
数组版本的unique_ptr重载了操作符[]操作符[]返回的是引用可以作为左值使用。
// unique_ptrint[] parr1(new int[3]); // 不指定初始值。
unique_ptrint[] parr1(new int[3]{ 33,22,11 }); // 指定初始值。
cout parr1[0] parr1[0] endl;
cout parr1[1] parr1[1] endl;
cout parr1[2] parr1[2] endl;unique_ptrAA[] parr2(new AA[3]{string(西施), string(冰冰), string(幂幂)});
cout parr2[0].m_name parr2[0].m_name endl;
cout parr2[1].m_name parr2[1].m_name endl;
cout parr2[2].m_name parr2[2].m_name endl; 二、智能指针shared_ptr
shared_ptr共享它指向的对象多个shared_ptr可以指向关联相同的对象在内部采用计数机制来实现use_count()。
当新的shared_ptr与对象关联时引用计数增加1。
当shared_ptr超出作用域时引用计数减1。当引用计数变为0时则表示没有任何shared_ptr与对象关联则释放该对象。 1、基本用法
shared_ptr的构造函数也是explicit但是没有删除拷贝构造函数和赋值函数。
1初始化
方法一
shared_ptrAA p0(new AA(西施)); // 分配内存并初始化。
方法二推荐采用
shared_ptrAA p0 make_sharedAA(西施); // C11标准效率更高。
方法三
AA* p new AA(西施);
shared_ptrAA p0(p); // 用已存在的地址初始化。
方法四
shared_ptrAA p0(new AA(西施));
shared_ptrAA p1(p0); // 用已存在的shared_ptr初始化计数加1。
shared_ptrAA p1p0; // 用已存在的shared_ptr初始化计数加1。
2使用方法 智能指针重载了*和-操作符可以像使用指针一样使用shared_ptr。 use_count()方法返回引用计数器的值。 unique()方法如果use_count()为1返回true否则返回false。 shared_ptr支持赋值左值的shared_ptr的计数器将减1右值shared_ptr的计算器将加1。 get()方法返回裸指针。 不要用同一个裸指针初始化多个shared_ptr。即不要用方法三方式构造多个shared_ptr。 不要用shared_ptr管理不是new分配的内存。
3用于函数的参数
与unique_ptr的原理相同。 传引用不能传值因为unique_ptr没有拷贝构造函数。 裸指针。
4不支持指针的运算、-、、--
2、更多细节 面试就爱考点技巧之类的
2用nullptr给shared_ptr赋值将把计数减1如果计数为0将释放对象空的shared_ptrnullptr。
4std::move()可以转移对原始指针的控制权。还可以将unique_ptr转移成shared_ptr。
5reset()改变与资源的关联关系。
pp.reset(); // 解除与资源的关系资源的引用计数减1。
pp. reset(new AA(bbb)); // 解除与资源的关系资源的引用计数减1。关联新资源。
6swap()交换两个shared_ptr的控制权。
void swap(shared_ptrT _Right);
7shared_ptr也可象普通指针那样当指向一个类继承体系的基类对象时也具有多态性质如同使用裸指针管理基类对象和派生类对象那样。
8shared_ptr不是绝对安全如果程序中调用exit()退出全局的shared_ptr可以自动释放但局部的shared_ptr无法释放。
9shared_ptr提供了支持数组的具体化版本。
数组版本的shared_ptr重载了操作符[]操作符[]返回的是引用可以作为左值使用。
10shared_ptr的线程安全性 shared_ptr的引用计数本身是线程安全引用计数是原子操作。 多个线程同时读同一个shared_ptr对象是线程安全的。 如果是多个线程对同一个shared_ptr对象进行读和写则需要加锁。 多线程读写shared_ptr所指向的同一个对象不管是相同的shared_ptr对象还是不同的shared_ptr对象也需要加锁保护。
11如果unique_ptr能解决问题就不要用shared_ptr。unique_ptr的效率更高占用的资源更少。
3、智能指针的删除器
智能指针构造函数第二个参数一般用默认的但可以指定删除器。
在默认情况下智能指针过期的时候用delete原始指针;释放它管理的资源。
程序员可以自定义删除器改变智能指针释放资源的行为。
删除器可以是全局函数、仿函数和Lambda表达式形参为原始指针。
调用
shared_ptrAA pa1(new AA(西施a), deletefunc); // 第二个参数一般都默认不写但可以自定义删除器。
三、智能指针weak_ptr
1、shared_ptr存在的问题
shared_ptr内部维护了一个共享的引用计数器多个shared_ptr可以指向同一个资源。
如果出现了循环引用的情况引用计数永远无法归0资源不会被释放。
2、weak_ptr是什么
weak_ptr 是为了配合shared_ptr而引入的它指向一个由shared_ptr管理的资源但不影响资源的生命周期。也就是说将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。
不论是否有weak_ptr指向如果最后一个指向资源的shared_ptr被销毁资源就会被释放。
weak_ptr更像是shared_ptr的助手而不是智能指针。
3、如何使用weak_ptr
weak_ptr没有重载 -和 *操作符不能直接访问资源。
有以下成员函数
operator(); // 把shared_ptr或weak_ptr赋值给weak_ptr。
expired(); // 判断它指资源是否已过期已经被销毁。
lock(); // 返回shared_ptr如果资源已过期返回空的shared_ptr。
reset(); // 将当前weak_ptr指针置为空。
swap(); // 交换。
weak_ptr不控制对象的生命周期但是它知道对象是否还活着。
用lock()函数把它可以提升为shared_ptr如果对象还活着返回有效的shared_ptr如果对象已经死了提升会失败返回一个空的shared_ptr。
提升的行为lock()是线程安全的。