EC笔记:第3部分:15、对原始资源的访问
2018-06-17 23:29:09来源:未知 阅读 ()
使用对象来管理资源,可以避免因个人疏忽带来的一些低级错误,但是不是每件事都是称心如意的。
一些函数依然使用原始的资源对象,那么我们就需要为这些函数提供一个接口,让他们可以获取到原始对象。
继续拿13节的智能指针说事,先上代码:
//SFAutoPtr.h
#pragma once
template<typename T>
class SFAutoPtr {
private:
T* pointer; //对象指针
size_t *ref_count; //引用计数
void dec() { //减少引用计数
if(*ref_count == 0) { //如果当前引用计数为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;
}
这样的代码怎么办?
对此我只能说:自作孽,不可活~~~
一般使用对象管理资源,都会提供接口访问原始对象。是使用隐式访问还是显式访问,这主要看实际需求,是为程序员带来便捷还是给程序员带来安全,你说了算~~~
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- OpenCV开发笔记(五十九):红胖子8分钟带你深入了解分水岭 2020-05-24
- 算法笔记刷题6 ( PAT 1003我要通过 ) 2020-05-08
- C++基础 学习笔记六:复合类型之数组 2020-04-25
- C++基础 学习笔记五:重载之运算符重载 2020-04-23
- C++基础 学习笔记四:重载之函数重载 2020-04-22
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash