0x01  智能指针简介

    所谓智能指针(smart pointer)就是智能/自动化的管理指针所指向的动态资源的释放。它是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露。它的一种通用实现技术是使用引用计数(reference count)。

    使用智能指针需要头文件 #include<memory> 。

     C++11从boost库中引入了unique_ptr, shared_ptr, weak_ptr,并舍弃了c98的auto_ptr。

0x02  auto_ptr

       C++11从boost库中引入了unique_ptr, shared_ptr, weak_ptr,并舍弃了c98的auto_ptr。

      C++标准程序库描述:“auto_ptr是一种智能指针,帮助程序员防止'被异常抛出时发生资源泄露'”。它在对象析构的时候自动释放资源,并模仿了原始指针的操作,重载了operator*和operator->,允许程序员向使用原始指针一样使用auto_ptr(但是没有重载所有的指针算术运算),并减少程序员显示的处理异常发生时代码的复杂度与失误。

   该指针的定义形式:auto_ptr<type> ptr(new type()); 其中 type 是指针指向的类型。

     例如:auto_ptr<int> ptr(new int(4));

   当然也可以先定义,后赋值:auto_ptr<int> ptr;ptr = auto_ptr<int>(new int (4));

     auto_ptr的作用:作用1:保证一个对象在某个时间只能被一个该种类型的智能指针所指向,就是通常所说的对象所有权。

            作用2:对指向的对象自动释放的作用。

#include "stdafx.h"
#include <Windows.h>
#include <memory>
#include <iostream>
using namespace std;
struct MyStruct
{
MyStruct() { cout << "MyStruct()\n"; }
~MyStruct() { cout << "~MyStruct()\n"; }
int i;
int j;
}; int main()
{
auto_ptr<MyStruct> ptr(new MyStruct);
ptr->i = 1;
ptr->j = 2;
(*ptr).i = 3;
(*ptr).j = 4;
return 0;
}

   auto_ptr是严格的拥有权类智能指针,使用时需要注意以下几点:

  1. auto_ptr之间不能共享拥有权
  2. auto_ptr对象通过赋值或构造转移拥有权,一旦拥有权转移,此auto_ptr所拥有的将是一个原始指针
  3. auto_ptr不适用于array
  4. auto_ptr不满足STL对容器元素的要求,因此不适用于STL容器。因为在拷贝和赋值之后,新的auto_ptr和旧的auto_ptr对象并不相等。
  5. 如果要阻止拥有权的转移,则应该在停止转移之前,将auto_ptr声明为const
  6. 不要使用auto_ptr的引用作为实参:因为你不知道拥有权到底有没有转移。如果你不需要转移拥有权,请使用const auto_ptr<class> &

0x03  shared_ptr

     shared_ptr采用引用计数的方式管理所指向的对象。当有一个新的shared_ptr指向同一个对象时(复制shared_ptr等),引用计数加1。当shared_ptr离开作用域时,引用计数减1。当引用计数为0时,释放所管理的内存。

这样做的好处在于减轻了程序员手动释放内存的负担。之前,为了处理程序中的异常情况,往往需要将指针手动封装到类中,通过析构函数来释放动态分配的内存;现在这一过程就可以交由shared_ptr完成了。

     一般使用make_shared来获得shared_ptr。

  

void Shared_PtrTest()
{
//shared_ptr Test
//Test One
cout << "test shared_ptr base usage:" << endl;
shared_ptr<string> v1 = make_shared<string>("");
if (v1 && v1->empty())
*v1 = "Chronic"; auto v2 = make_shared<string>("LSH");
cout << *v1 << ' ' << *v2 << endl; cout << "test shared_ptr use_count:" << endl;
cout << "v1 ReferenceCount:" << v1.use_count() << "\tv2 ReferenceCount:" << v2.use_count() << endl; auto v3 = v2;
cout << "v1 ReferenceCount:" << v1.use_count() << "\tv2 ReferenceCount:" << v2.use_count() << "\tv3 ReferenceCount:" << v3.use_count() << endl;
v2 = v1;
cout << "v1 ReferenceCount:" << v1.use_count() << "\tv2 ReferenceCount:" << v2.use_count() << "\tv3 ReferenceCount:" << v3.use_count() << endl; //Test Two
//使用一个new表达式返回的指针进行初始化。
cout << "test shared_ptr and new:" << endl;
shared_ptr<int> p4(new int(1024));
//shared_ptr<int> p5 = new int(1024); // 错误
cout << *p4 << endl; //Test Three
//不可混用new和shared_ptr!
cout << "不可混用new和shared_ptr!" << endl;
shared_ptr<int> p5(new int(1024));
process(p5);
int v5 = *p5;
cout << "v5: " << v5 << endl; int *p6 = new int(1024);
//shared_ptr<int> p6(new int(1024)); 正确做法
process(shared_ptr<int>(p6));
int v6 = *p6;
cout << "v6: " << v6 << endl;
/*
输出结果:
不可混用new和shared_ptr!
in process use_count:2
v5: 1024
in process use_count:1
v6: -572662307
*/ //Test Four
//shared_ptr可以通过reset方法重置指向另一个对象,此时原对象的引用计数减一。
//shared_ptr<string> v1 = make_shared<string>("LSH");
cout << "test shared_ptr reset:" << endl;
cout << "p1 cnt:" << v1.use_count() << endl;
v1.reset(new string("LSH Reset"));
cout << "p1 cnt:" << v1.use_count() << endl;
}

  

0x04  unique_ptr

    unique_ptr对于所指向的对象,如其名所示,是独占的。所以,不可以对unique_ptr进行拷贝、赋值等操作,但是可以通过release函数在unique_ptr之间转移控制权。

    对于拷贝的限制,有两个特殊情况,即unique_ptr可以作为函数的返回值和参数使用,这时虽然也有隐含的拷贝存在,但是并非不可行的。

  

void Unique_PtrTest()
{
//Test One
//unique_ptr对于所指向的对象,正如其名字所示,是 独占 的。
//所以,不可以对unique_ptr进行拷贝、赋值等操作,但是可以通过release函数在unique_ptr之间转移控制权。
cout << "test unique_ptr base usage:" << endl;
unique_ptr<int> up1(new int(1024));
cout << "up1: " << *up1 << endl;
unique_ptr<int> up2(up1.release());
cout << "up2: " << *up2 << endl;
//unique_ptr<int> up3(up1); // 错误,不可进行拷贝操作
//up2 = up1; // 错误,不可进行拷贝操作
unique_ptr<int> up4(new int(1025));
up4.reset(up2.release());
cout << "up4: " << *up4 << endl; //Test Two
//上述对于拷贝的限制,有两个特殊情况,
//即unique_ptr可以作为函数的返回值和参数使用,这时虽然也有隐含的拷贝存在,但是并非不可行的。
cout << "test unique_ptr parameter and return value:" << endl;
auto up5 = CloneFunction(1024);
cout << "up5: " << *up5 << endl;
process_unique_ptr(move(up5));
//cout<<"up5 after process: "<<*up5<<endl; //错误segmentfault
}

  

0x05  weak_ptr

     weak_ptr一般和shared_ptr配合使用。它可以指向shared_ptr所指向的对象,但是却不增加对象的引用计数。这样就有可能出现weak_ptr所指向的对象实际上已经被释放了的情况。因此,weak_ptr有一个lock函数,尝试取回一个指向对象的shared_ptr。

  

void Weak_PtrTest()
{
//weak_ptr一般和shared_ptr配合使用。
//它可以指向shared_ptr所指向的对象,但是却不增加对象的引用计数。
//这样就有可能出现weak_ptr所指向的对象实际上已经被释放了的情况。因此,weak_ptr有一个lock函数,尝试取回一个指向对象的shared_ptr。
cout << "test weak_ptr basic usage:" << endl;
auto p10 = make_shared<int>(1024);
weak_ptr<int> wp1(p10);
assert(p10.use_count() == 1);
cout << "p10 use_count: " << p10.use_count() << endl;
//p10.reset(new int(1025)); // this will cause wp1.lock() return a false obj
shared_ptr<int> p11 = wp1.lock();
assert(p11.use_count() == 2);
if (p11) cout << "wp1: " << *p11 << " use count: " << p11.use_count() << endl;
}

  

0x06   小结

  shared_ptr采用引用计数的方式管理所指向的对象。shared_ptr可以使用一个new表达式返回的指针进行初始化;但是,不能将一个new表达式返回的指针赋值给shared_ptr。

一旦将一个new表达式返回的指针交由shared_ptr管理之后,就不要再通过普通指针访问这块内存;shared_ptr可以通过reset方法重置指向另一个对象,此时原对象的引用计数减一。

  unique_ptr对于所指向的对象,是独占的;不可以对unique_ptr进行拷贝、赋值等操作,但是可以通过release函数在unique_ptr之间转移控制权;unique_ptr可以作为函数的返回值和参数使用。

  weak_ptr一般和shared_ptr配合使用;它可以指向shared_ptr所指向的对象,但是却不增加对象的引用计数;weak_ptr有一个lock函数,尝试取回一个指向对象的shared_ptr。

完整源码:

// 智能指针.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <Windows.h>
#include <string>
#include <iostream>
#include<memory>
#include<assert.h>
using namespace std;
void Shared_PtrTest();
void Unique_PtrTest();
void Weak_PtrTest(); int main()
{
//Shared_PtrTest();
//Unique_PtrTest();
Weak_PtrTest();
} void process(shared_ptr<int> ptr)
{
cout << "in process use_count:" << ptr.use_count() << endl;
} void Shared_PtrTest()
{
//shared_ptr Test
//Test One
cout << "test shared_ptr base usage:" << endl;
shared_ptr<string> v1 = make_shared<string>("");
if (v1 && v1->empty())
*v1 = "Chronic"; auto v2 = make_shared<string>("LSH");
cout << *v1 << ' ' << *v2 << endl; cout << "test shared_ptr use_count:" << endl;
cout << "v1 ReferenceCount:" << v1.use_count() << "\tv2 ReferenceCount:" << v2.use_count() << endl; auto v3 = v2;
cout << "v1 ReferenceCount:" << v1.use_count() << "\tv2 ReferenceCount:" << v2.use_count() << "\tv3 ReferenceCount:" << v3.use_count() << endl;
v2 = v1;
cout << "v1 ReferenceCount:" << v1.use_count() << "\tv2 ReferenceCount:" << v2.use_count() << "\tv3 ReferenceCount:" << v3.use_count() << endl; //Test Two
//使用一个new表达式返回的指针进行初始化。
cout << "test shared_ptr and new:" << endl;
shared_ptr<int> p4(new int(1024));
//shared_ptr<int> p5 = new int(1024); // 错误
cout << *p4 << endl; //Test Three
//不可混用new和shared_ptr!
cout << "不可混用new和shared_ptr!" << endl;
shared_ptr<int> p5(new int(1024));
process(p5);
int v5 = *p5;
cout << "v5: " << v5 << endl; int *p6 = new int(1024);
//shared_ptr<int> p6(new int(1024)); 正确做法
process(shared_ptr<int>(p6));
int v6 = *p6;
cout << "v6: " << v6 << endl;
/*
输出结果:
不可混用new和shared_ptr!
in process use_count:2
v5: 1024
in process use_count:1
v6: -572662307
*/ //Test Four
//shared_ptr可以通过reset方法重置指向另一个对象,此时原对象的引用计数减一。
//shared_ptr<string> v1 = make_shared<string>("LSH");
cout << "test shared_ptr reset:" << endl;
cout << "p1 cnt:" << v1.use_count() << endl;
v1.reset(new string("LSH Reset"));
cout << "p1 cnt:" << v1.use_count() << endl;
} unique_ptr<int> CloneFunction(int p)
{
return unique_ptr<int>(new int(p));
} void process_unique_ptr(unique_ptr<int> up)
{
cout << "process unique ptr: " << *up << endl;
} void Unique_PtrTest()
{
//Test One
//unique_ptr对于所指向的对象,正如其名字所示,是 独占 的。
//所以,不可以对unique_ptr进行拷贝、赋值等操作,但是可以通过release函数在unique_ptr之间转移控制权。
cout << "test unique_ptr base usage:" << endl;
unique_ptr<int> up1(new int(1024));
cout << "up1: " << *up1 << endl;
unique_ptr<int> up2(up1.release());
cout << "up2: " << *up2 << endl;
//unique_ptr<int> up3(up1); // 错误,不可进行拷贝操作
//up2 = up1; // 错误,不可进行拷贝操作
unique_ptr<int> up4(new int(1025));
up4.reset(up2.release());
cout << "up4: " << *up4 << endl; //Test Two
//上述对于拷贝的限制,有两个特殊情况,
//即unique_ptr可以作为函数的返回值和参数使用,这时虽然也有隐含的拷贝存在,但是并非不可行的。
cout << "test unique_ptr parameter and return value:" << endl;
auto up5 = CloneFunction(1024);
cout << "up5: " << *up5 << endl;
process_unique_ptr(move(up5));
//cout<<"up5 after process: "<<*up5<<endl; //错误segmentfault
} void Weak_PtrTest()
{
//weak_ptr一般和shared_ptr配合使用。
//它可以指向shared_ptr所指向的对象,但是却不增加对象的引用计数。
//这样就有可能出现weak_ptr所指向的对象实际上已经被释放了的情况。因此,weak_ptr有一个lock函数,尝试取回一个指向对象的shared_ptr。
cout << "test weak_ptr basic usage:" << endl;
auto p10 = make_shared<int>(1024);
weak_ptr<int> wp1(p10);
assert(p10.use_count() == 1);
cout << "p10 use_count: " << p10.use_count() << endl;
//p10.reset(new int(1025)); // this will cause wp1.lock() return a false obj
shared_ptr<int> p11 = wp1.lock();
assert(p11.use_count() == 2);
if (p11) cout << "wp1: " << *p11 << " use count: " << p11.use_count() << endl;
}

  

C++11智能指针 share_ptr,unique_ptr,weak_ptr用法的更多相关文章

  1. C++11智能指针(unique_ptr、shared_ptr、weak_ptr)(转)

    原文地址:https://blog.csdn.net/king_way/article/details/95536938

  2. c++11 智能指针 unique_ptr、shared_ptr与weak_ptr

    c++11 智能指针 unique_ptr.shared_ptr与weak_ptr C++11中有unique_ptr.shared_ptr与weak_ptr等智能指针(smart pointer), ...

  3. C++11智能指针之std::unique_ptr

    C++11智能指针之std::unique_ptr   uniqut_ptr是一种对资源具有排他性拥有权的智能指针,即一个对象资源只能同时被一个unique_ptr指向. 一.初始化方式 通过new云 ...

  4. 【C++11新特性】 C++11智能指针之weak_ptr

    如题,我们今天要讲的是C++11引入的三种智能指针中的最后一个:weak_ptr.在学习weak_ptr之前最好对shared_ptr有所了解.如果你还不知道shared_ptr是何物,可以看看我的另 ...

  5. C++11——智能指针

    1. 介绍 一般一个程序在内存中可以大体划分为三部分——静态内存(局部的static对象.类static数据成员以及所有定义在函数或者类之外的变量).栈内存(保存和定义在函数或者类内部的变量)和动态内 ...

  6. 详解C++11智能指针

    前言 C++里面的四个智能指针: auto_ptr, unique_ptr,shared_ptr, weak_ptr 其中后三个是C++11支持,并且第一个已经被C++11弃用. C++11智能指针介 ...

  7. C++11 智能指针

    C++ 11标准库引入了几种智能指针 unique_ptr shared_ptr weak_ptr C++内存管理机制是当一个变量或对象从作用域过期的时候就会从内存中将他干掉.但是如果变量只是一个指针 ...

  8. C++11智能指针原理和实现

    一.智能指针起因 在C++中,动态内存的管理是由程序员自己申请和释放的,用一对运算符完成:new和delete. new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针: delete:指向 ...

  9. 深入学习c++--智能指针(三) unique_ptr

    1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智 ...

随机推荐

  1. WebStrom配置

    1.下载安装Node.jshttps://nodejs.org/en/download/2.配置node路径3.修改文件默认字符集

  2. Spring Batch Bean 校验 API 支持

    这个发布版本带来了一个新的  ValidatingItemProcessor 实现,这个实现被称为 BeanValidatingItemProcessor.能够让你使用 Bean Validation ...

  3. Linux中计划任务、周期性任务设置

    Linux中计划任务.周期性任务设置 计划任务:指在未来的特定时间里,执行一次某一特定任务.当然,如果同一任务需要在不同时间点执行执行两次.三次或多次,可以视为多个一次看待. 周期性任务:指某一任务需 ...

  4. DedecmsV5.7本地上传缩略图无法自动添加水印的解决方法

    问题:dedecms后台 系统->图片水印设置 图片水印设置有开启了,但是本地上传缩略图无法自动添加水印 网上有很多资料,所以记录一下 1.打开dede(实际项目后台文件夹)/archives_ ...

  5. Leetcode 980. 不同路径 III

    980. 不同路径 III  显示英文描述 我的提交返回竞赛   用户通过次数42 用户尝试次数43 通过次数46 提交次数60 题目难度Hard 在二维网格 grid 上,有 4 种类型的方格: 1 ...

  6. 稳定获取Android设备唯一码(UUID)的解决方案

    最近做的一个项目中需要用到Android设备唯一码(UUID)来标识一台设备, Android中设备唯一码有很多,如:MAC地址.IMEI号(DeviceId).IMSI号.ANDROID_ID.序列 ...

  7. SQLserver如何创建一个表

    例如: create table news(news_id int primary key identity(1,1),news_title varchar(50) not null,news_aut ...

  8. 在ubuntu14中搭建邮箱服务器

    1.前提准备 1.1在服务器上安装ubuntu14 1.2为ubuntu14配置静态ip 使用命令 sudo vim /etc/network/interfaces打开配置文件 修改内容如下: 使用命 ...

  9. dubbo初认知(dubbo和springCloud关系,在微服务架构中的作用等)(持续更新中)

    一:dubbo是什么? dobbuo是阿里开源的一个高性能优秀的服务框架, 可通过高性能的 RPC 实现服务的输出和输入功能,使得应用可以和 高性能的rpc实现输入和输出的功能,可以了  Spring ...

  10. [luogu P1438] 无聊的数列

    [luogu P1438] 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个 ...