1、什么是智能指针?

  所谓智能指针就是,看起来,用起来,感觉起来都像原始指针,但是提供了更多功能。

2、使用智能指针取代原始指针,可以获得更多的控制权。如下:

  a、在构造和析构的时候,可以做一些事。

  b、在复制和赋值的时候,可以做一些事。

  c、在解引用的时候,可以做一些事。

3、智能指针可以对不同类型的指针进行封装,因此智能指针是一个模板类。

4、智能指针对原始指针封装,内含一个原始指针,为了用起来像指针,重载->和*,->返回原始指针,*返回对象的引用,两个重载操作符都不改变智能指针,因此是const成员方法。

5、考虑auto_ptr,拥有权转移,auto_ptr的copy构造会修改rhs,因此rhs不是const T&,而是T&。C++默认是传值,导致拥有权转移,如果期望拥有权不转移,使用传引用。

6、解引用操作符*,必须返回引用,不能返回对象。因为解引用操作符,可能返回T的子类。如果返回对象,首先导致对象复制,其次可能照成对象切割,失去多态功能。

7、判断智能指针是否为NULL。对于原始指针,使用if(pa == null),但是对于智能指针,不能这样使用,因为智能指针是个对象。怎么解决这个问题呢?

  a、增加isNull方法,缺点是与原始指针的用法不一致。
  b、为了与原始指针的用法一致,增加隐式类型转换操作符,operator void*()。但是这会导致一个问题,任意两个智能指针,都能进行比较,因为他们都可以隐式转化为void*,这不是我们所期望的。

8、智能指针如何暴露出原始指针?

  使用&*pa,合法,先取引用,再取地址。但是这种写法太难看了。增加隐式类型转换操作符operator T*(),这会引入一个问题,不是我们期望的转换,编译器也会偷偷进行。使用get方法,返回原始指针,避免编译器偷偷地进行转换。
注意:暴露原始指针是危险的,因为暴露出去的原始指针,不再受控。比如:智能指针把资源delete了,外面的原始指针就是野指针了。或者外面的指针执行了delete,智能指针管理的指针指向垃圾。

9、考虑继承,C++是强制类型的。Smart_Ptr<Base>与Smart_Ptr<Derived>是两个完全不同的类,之间没有任何关系,更谈不上继承。那么问题来了,对于原始指针可以指向子类对象,而智能指针不行。如下:
  Base* b = new Derived(); // OK
  Smart_Ptr<Base> b = Smart_Ptr<Derived>(new Derived); //Error
  编译失败,这不合理,怎么解决这个问题呢?

10、首先想到的是,隐式类型转换。这显然不合理,对原始指针类型的所有转换都要考虑。

11、有没有更好的解决办法呢?

使用C++语言的新特性,成员方法模版。隐式类型转换操作符声明为成员方法模版,如下:
template <typename NewType>
operator Smart_Ptr<NewType>()
{
  return Smart_Ptr<NewType>(this->ptr);
}
考虑Smart_Ptr<Base> b = Smart_Ptr<Derived>(new Derived)的执行过程:
  a、编译器首先看看Smart_Ptr<Base>有没有一个构造方法,该构造方法只需要一个形参,形参类型为Smart_Ptr<Derived>,没有找到;
  b、编译器看看Smart_Ptr<Derived>有没有隐式类型转换操作符,将Smart_Ptr<Derived>转换为Smart_Ptr<Base>,没有找到;
  c、编译器尝试将成员方法模版实例化出来一个合适的方法,也就是一个隐式类型转换操作符,使得隐式类型转换成功。
将NewType实例化为模版实参Base,在return语句的构造方法中,使用原始指针Derived,初始化Base指针,构造出Smart_Ptr<Base>,当然可以。
  注意,这里还放大了权限,只要NewType指针可以转换为T指针,那么Smart_Ptr<NewType>对象就可以赋值给Smart_Ptr<T>对象。
  成员方法模版,还有两个问题。首先,考虑fun(Base&),fun(Derived&),对于Derived derived1, fun(derived1)的调用,fun(Derived&)的匹配程度更高。但是,对于成员方法模版,都可实例出一个方法,使得调用成功,并且匹配程度是一样的,这就导致不确定的调用,编译错误。其次,成员方法模版移植性不高,有些编译器不支持。

12、智能指针与const
  C++设计理念是,最小特权原则。让别人做一件事,尽量限制他的权利。一个典型的例子就是,C++在传递引用过程中,可以缩小权力,但不能放大权利。
  原始指针与const有两种关系:a、指向const对象的指针,不能修改指向的对象;b、指针常量,不能修改指向。因此,对于智能指针,我们也希望有这种弹性。但是,对于智能指针只有一个地方可以const,修饰智能指针对象,也就相当于修饰指针。那怎么样修饰指向的对象呢?使用Smart_Ptr<const T>。那么问题来了,Smart_Ptr<T> 与Smart_Ptr<const T>是两个完全不同的类型,当然不能赋值。该怎么办呢?不要再想着隐式类型转换了,因为隐式类型转换会导致非预期的转换。考虑里氏代换,子类能力更大。从const T 到T,是能力变大的过程,因此可以考虑Smart_Ptr<T>: Smart_Ptr<const T>

【M28】智能指针的更多相关文章

  1. C++ 智能指针auto_ptr

    template<class T> class auto_ptr { public: ); // Item M5 有“explicitfor”// 的描述 template<clas ...

  2. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  3. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  4. C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...

  5. EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针

    一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...

  6. 智能指针shared_ptr的用法

    为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...

  7. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

  8. 基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

    本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...

  9. C++ 引用计数技术及智能指针的简单实现

    一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...

随机推荐

  1. hdu 3537(博弈,翻硬币)

    题意:给定了每个正面朝上的硬币的位置,然后每次可以翻1,2,3枚硬币,并且最右边的硬币开始必须是正面朝上的. 分析: 约束条件6:每次可以翻动一个.二个或三个硬币.(Mock Turtles游戏) 初 ...

  2. Codeforces Round #214 (Div. 2) c题(dp)

    C. Dima and Salad time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  3. cookie跨域,跨目录访问及单点登录。

    首先普及下域名的知识: 域名: baidu.com    // 一级域名  A play.baidu.com  //  二级域名 B abc.play.baidu.com // 三级域名  C 数有几 ...

  4. 在Mac OS X 通过抓包、“第三方下载工具”加速下载、安装APP或系统

    #!/bin/bash ######################################################################################## ...

  5. ASP.NET Cookie对象到底是毛啊?(简单小例子)

    记得刚接触asp.net的时候,就被几个概念搞的头痛不已,比如Request,Response,Session和Cookie.然后还各种在搜索引擎搜,各种问同事的,但是结果就是自己还是很懵的节奏. 那 ...

  6. 状态管理cookie 案例

    1状态管理:服务器为了追踪同一个客户端发出的请求,将多次交互看成一个整体看待 2:cookie的生存时间,默认情况下,cookie保存在浏览器内存中,只要不关闭浏览器,cookie就一直存在 如果希望 ...

  7. 在Chrome Console中加载jQuery

    var jq = document.createElement('script'); jq.src = "//ajax.googleapis.com/ajax/libs/jquery/1/j ...

  8. Scrum概述

    • 敏捷方法是一类软件开发流程的泛称: • 敏捷方法是相对于传统的瀑布式软件过程提出的: • 敏捷方法可以用敏捷宣言(4条).敏捷原则(12条)来概括: • 敏捷原则通过一系列的敏捷实践来体现出来: ...

  9. hadoop的kerberos认证

    言归正传,介绍过hadoop的simple认证和kerberos后,我们在这一章介绍hadoop的kerberos认证 我们还使用hadoop集群的机器. OS 版本: Centos6.4 Kerbe ...

  10. 《Linux设备驱动程序》 笔记2

    驱动代码hello.c #include <linux/init.h> #include <linux/module.h> static int hello_init(void ...