使用对象来管理资源,可以避免因个人疏忽带来的一些低级错误,但是不是每件事都是称心如意的。

一些函数依然使用原始的资源对象,那么我们就需要为这些函数提供一个接口,让他们可以获取到原始对象。

继续拿13节的智能指针说事,先上代码:

//SFAutoPtr.h

#pragma once

template<typename T>

class SFAutoPtr {

private:

T* pointer;
//对象指针

size_t *ref_count;
//引用计数

void
dec()
{
//减少引用计数

if(*ref_count ==
0)
{
,则应该释放资源

delete pointer;

pointer = nullptr;

delete ref_count;

ref_count = nullptr;

return;

}

--*ref_count;

}

void
inc()
{
//增加引用计数

++*ref_count;

}

public:

SFAutoPtr()
:
//默认构造函数,生成一个指针

pointer(new T),

ref_count(new
size_t(0))
{}

template<typename ... Init_Type>

SFAutoPtr(Init_Type...args)
:
//带参数的构造函数,对象带有指针

pointer(new T(args...)),

ref_count(new
size_t(0))
{}

SFAutoPtr(const SFAutoPtr<T>& other)
{
//拷贝构造函数,增加引用计数

pointer = other.pointer;

ref_count = other.ref_count;

inc();

}

bool
operator==(const SFAutoPtr<T>& other)
const{
//等于操作符,判断指针是否相等,这时候不应该比较ref_count

return pointer == other.pointer;

}

const SFAutoPtr<T>&
operator=(const SFAutoPtr<T>& other)
{
//赋值运算符,需要将当前引用计数-1,赋值的引用计数+1

if(this
==
&other)

return
*this;

dec();

pointer = other.pointer;

ref_count = other.ref_count;

inc();

return
*this;

}

T operator*(int)
{
//解引用运算符

return
*pointer;

}

operator T*()
{
//指针运算符,适用于使用指针作为参数的函数

return pointer;

}

T*
operator->()
{
//成员访问操作符

return pointer;

}

~SFAutoPtr()
{
//析构函数,需要将引用计数-1

dec();

}

};

注意其中的:

operator T*()
{
//指针运算符,适用于使用指针作为参数的函数

return pointer;

}

这里就是为需要T*类型作为参数的函数提供接口,如下:

#include <iostream>

using
namespace std;

void
func(int
*){

cout<<"hello world"<<endl;

}

int
main(){

SFAutoPtr<int> t;

func(t);

}

SFAutoPtr<int>能够很好地适应int*类型的参数,这为编码提供了不少方便,但是随之也带来了一些安全隐患:

例如,有人可能写出下面这样的代码(没错,就是小明!!!):

#include <iostream>

using
namespace std;

int
*p;

void
setP(){

p=SFAutoPtr<int>(5);

}

int
main(){

setP();

cout<<*p<<endl;

}

这里不会输出5,而是会输出一个随机值,甚至程序崩溃,因为我们使用了对象管理资源,对象在销毁时,资源也会被释放。导致这一现象的原因是AFAutoPtr<int>被隐式转换为了int*,避免这种调用的方法之一就是,不再提供隐式转换,确保编写出的每一个转换都是程序员想要的,使用get()而非operator T*,将原实现中的operator T*操作符替换为get()函数。有人可能要问,如果程序员非得写出:

#include <iostream>

using
namespace std;

int
*p;

void
setP(){

SFAutoPtr<int>
tmp(5);

p=tmp.get();

}

int
main(){

setP();

cout<<*p<<endl;

}

这样的代码怎么办?

对此我只能说:自作孽,不可活~~~

一般使用对象管理资源,都会提供接口访问原始对象。是使用隐式访问还是显式访问,这主要看实际需求,是为程序员带来便捷还是给程序员带来安全,你说了算~~~

EC笔记:第3部分:15、对原始资源的访问的更多相关文章

  1. Effective C++ -----条款15:在资源管理类中提供对原始资源的访问

    APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法. 对原始资源的访问可能经由显示转换(.get()成员函数或者指针取值 ...

  2. Effective C++(15) 在资源管理类中提供对原始资源的访问

      问题聚焦:     资源管理类是为了对抗资源泄露.     如果一些函数需要访问原始资源,资源管理类应该怎么做呢?        关于资源管理的概念总是显得那么的高大上,其实只是抽象一点. 下面用 ...

  3. Effective C++ 条款15、16 在资源管理类中提供对原始资源的访问||成对使用new 与 delete要采取相同形式

    1.在资源管理类中提供对原始资源的访问     前几个条款很棒,它们是对抗资源泄露的壁垒,但很多APIs直接指向 资源,这个时候,我们需要直接访问原始资源.     这里,有两种方法解决上述问题,我们 ...

  4. 条款15:在资源管理类中提供对原始资源的访问(Provide access to raw resources in resource-managing classes)

    NOTE: 1.APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法. 2.对原始资源的访问可能经由显示转换或隐式转换.一 ...

  5. [Effective C++ --015]在资源管理类中提供对原始资源的访问

    引言 资源管理类是防止资源泄漏的有力武器,但是许多APIs直接指涉资源,除非你发誓永不使用这样的APIs,否则只得绕过资源管理对象(resource-managing objects)直接访问原始资源 ...

  6. 【Spring学习笔记-MVC-14】Spring MVC对静态资源的访问

    作者:ssslinppp       参考链接: http://www.cnblogs.com/luxh/archive/2013/03/14/2959207.html  http://www.cnb ...

  7. 读书笔记_Effective_C++_条款十五:在资源类管理类中提供对原始资源的访问

    void f(int* a) { cout <<* a << endl; } int main() { shared_ptr<int> p(new int(3)); ...

  8. EC笔记:第4部分:22、所有成员都应该是private的

    EC笔记:第4部分:22.所有成员都应该是private的 更简单的访问 用户不用记得什么时候该带上括号,什么时候不用带上括号(因为很确定的就要带上括号) 访问限制 对于public的成员变量,我们可 ...

  9. EC笔记:第二部分:12、复制对象时勿忘其每一个成分

    EC笔记:第二部分:12.复制对象时勿忘其每一个成分 1.场景 某些时候,我们不想使用编译器提供的默认拷贝函数(包括拷贝构造函数和赋值运算符),考虑以下类定义: 代码1: class Point{ p ...

随机推荐

  1. Git小技巧 - 指令别名及使用Beyond Compare作为差异比较工具

    前言 本文主要写给使用命令行来操作Git的用户,用于提高Git使用的效率.至于使用命令还是GUI(Tortoise Git或VS的Git插件)就不在此讨论了,大家根据自己的的喜好选择就好.我个人是比较 ...

  2. ASP.NET Core 中文文档目录

    翻译计划 五月中旬 .NET Core RC2 如期发布,我们遂决定翻译 ASP.NET Core 文档.我们在 何镇汐先生. 悲梦先生. 张仁建先生和 雷欧纳德先生的群中发布了翻译计划招募信息,并召 ...

  3. iptables

    一.在服务器上打开 22.80.9011端口: iptables -A INPUT -p tcp --dport 9011 -j ACCEPT iptables -A OUTPUT -p tcp -- ...

  4. Collection集合

    一些关于集合内部算法可以查阅这篇文章<容器类总结>. (Abstract+) Collection 子类:List,Queue,Set 增: add(E):boolean addAll(C ...

  5. The first documents

    Mark~ 赶在2016年的年末,来开了一个blog. 想想以前开设的blog还是十多年前,时光飞逝~~ 开设这个blog的主要目的是用于自己平时一些知识的记录. 希望能在未来很长一段时间能坚持学习与 ...

  6. thinkphp-无限分类下根据任意部门获取顶级部门ID

    根据所得到的部门编号获取顶级部门ID: 参数 - department_id 表格组织架构: tab_departments department_id parent_id name 1 1 顶级 2 ...

  7. Mono 3.2.3 Socket功能迎来一稳定的版本

    由于兴趣自己业余时间一直在搞.net下面的通讯应用,mono的存在得以让.NET程序轻松运行在Linux之下.不过经过多尝试Socket相关功能在Mono下的表现并不理想.不管性能还是吞吐能力方面离我 ...

  8. 【腾讯Bugly干货分享】彻底弄懂 Http 缓存机制 - 基于缓存策略三要素分解法

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/qOMO0LIdA47j3RjhbCWUEQ 作者:李 ...

  9. [Intel Edison开发板] 04、Edison开发基于nodejs和redis的服务器搭建

    一.前言 intel-iot-examples-datastore 是Intel提供用于所有Edison开发板联网存储DEMO所需要的服务器工程.该工程是基于nodejs和redis写成的一个简单的工 ...

  10. 配置文件Java读写

    今天把配置文件的Bug修复了,总结一下Java配置文件如何读写 配置文件的格式 以.properties后缀结尾,内容不出现空格和双引号 //config.properties Driver=com. ...