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

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

继续拿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. Oracle安装部署,版本升级,应用补丁快速参考

    一.Oracle安装部署 1.1 单机环境 1.2 Oracle RAC环境 1.3 Oracle DataGuard环境 1.4 主机双机 1.5 客户端部署 二.Oracle版本升级 2.1 单机 ...

  2. EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)

    前言 Entity Framework 延伸系列目录 今天我们来聊聊EF的日志记录. 一个好的数据库操作记录不仅仅可以帮你记录用户的操作, 更应该可以帮助你获得效率低下的语句来帮你提高运行效率 废话不 ...

  3. js面向对象学习 - 对象概念及创建对象

    原文地址:js面向对象学习笔记 一.对象概念 对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”.也就是一组名值对的无序集合. 对象的特性(不可直接访问),也就是属性包含两种,数 ...

  4. 设计模式C#合集--单例模式

    单例模式 代码: 第一种: private static Singleton singleton = null; private Singleton() { } public static Singl ...

  5. FineReport如何用JDBC连接阿里云ADS数据库

    在使用FineReport连接阿里云的ADS(AnalyticDB)数据库,很多时候在测试连接时就失败了.此时,该如何连接ADS数据库呢? 我们只需要手动将连接ads数据库需要使用到的jar放置到%F ...

  6. 【转】ofbiz数据库表结构设计

    真心不错的文章,可以加深对企业信息化的设计理解:) http://blog.sina.com.cn/s/blog_a2ca5d8c01017fa0.html http://blog.sina.com. ...

  7. Spring7:基于注解的Spring MVC(下篇)

    Model 上一篇文章<Spring6:基于注解的Spring MVC(上篇)>,讲了Spring MVC环境搭建.@RequestMapping以及参数绑定,这是Spring MVC中最 ...

  8. Spring6:基于注解的Spring MVC(上篇)

    什么是Spring MVC Spring MVC框架是一个MVC框架,通过实现Model-View-Controller模式来很好地将数据.业务与展现进行分离.从这样一个角度来说,Spring MVC ...

  9. JAVA通信系列一:Java Socket技术总结

    本文是学习java Socket整理的资料,供参考. 1       Socket通信原理 1.1     ISO七层模型 1.2     TCP/IP五层模型 应用层相当于OSI中的会话层,表示层, ...

  10. ABP框架搭建项目系列教程基础版完结篇

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...