C语言 句柄,c++中句柄是什么意思

C语言 句柄,c++中句柄是什么意思,详解C++句柄类

本文给大家详细分析了C handle类的相关知识点,有需要的朋友可以学习参考一下。

上一个文件介绍了C proxy类的使用场景和实现方法,但是proxy类有一些缺陷,就是每个proxy类都会新建一个对象,无法避免一些不必要的内存拷贝。本文引入了handle类,它可以保持代理类的多态性,避免不必要的对象复制。

我们先来看一个简单的字符串封装类:MyString。为了方便查看代码,函数的声明和实现放在一起。

类MyString

{

公共:

//默认构造函数

MyString()

{

STD:cout ' MyString()' STD:endl;

buf _=new char[1];

buf _[0]=' \ 0 ';

len _=0;

}

constchar *参数的构造函数

MyString(const char* str)

{

STD:cout ' MyString(const char * str)' STD:endl;

if (str==nullptr)

{

len _=0;

buf _=new char[1];

buf _[0]=' \ 0 ';

}

其他

{

len _=strlen(str);

buf _=new char[len _ 1];

strcpy_s(buf_,len_ 1,str);

}

}

//复制构造函数

MyString(const MyString other)

{

STD:cout ' MyString(const MyString other)' STD:endl;

len _=strlen(other . buf _);

buf _=new char[len _ 1];

strcpy_s(buf_,len_ 1,other . buf _);

}

//str 1=str 2;

const MyString运算符=(const MyString other)

{

STD:cout ' MyString:operator=(const MyString other)' STD:endl;

//确定是否是自赋值。

如果(这个!=其他)

{

if (other.len_ this-len_)

{

删除[]buf _;

buf _=new char[other . len _ 1];

}

len _=other.len _

strcpy_s(buf_,len_ 1,other . buf _);

}

返回* this

}

//str='你好!';

const MyString运算符=(const char* str)

{

断言(str!=nullptr);

STD:cout ' operator=(const char * str)' STD:endl;

size _ t strLen=strLen(str);

if (strLen len_)

{

删除[]buf _;

buf _=new char[strLen 1];

}

len _=strLen

strcpy_s(buf_,len_ 1,str);

返回* this

}

//str='hello '

void运算符=(const char* str)

{

断言(str!=nullptr);

STD:cout ' operator=(const char * str)' STD:endl;

if (strlen(str)==0)

{

返回;

}

size _ t new buflen=strlen(str)len _ 1;

char * new buf=new char[new buflen];

strcpy_s(newBuf,newBufLen,buf _);

strcat_s(newBuf,newBufLen,str);

删除[]buf _;

buf _=newBuf

len _=strlen(buf _);

}

//重载ostream的运算符,支持std:cout MyString的输出。

friend std:ostream运算符(std:ostream out,MyString obj)

{

out obj . c _ str();

退了出来;

}

//返回C样式的字符串

const char* c_str()

{

返回buf _;

}

//返回字符串长度

size_t长度()

{

return len _;

}

~MyString()

{

删除[]buf _;

buf _=nullptr

}

私人:

char * buf _;

size _ t len _

};

看一个测试程序。

#包含“MyString.h”

int _tmain(int argc,_TCHAR* argv[])

{

MyString str 1(' hello ~ ~ ');

MyString str2=str1

MyString str3=str1

std:cout 'str1=' str1 ',str2=' str2 ',str3=' str3

返回0;

}

输出内容如下:

如您所见,定义了三个MyString对象。str2和str3是通过复制str1构造的,str2和str3的内容在程序运行过程中没有被修改,但是str1和str2已经将str1缓冲区的内容复制到了自己的缓冲区中。其实这里可以做一个优化,就是str1和str2在复制和构造的时候可以直接指向str1的内存,这样就避免了重复的内存复制。但这将导致一些新的问题:

1.多个指针指向同一个动态内存。什么时候释放内存?谁发布的?

2.如果一个对象需要修改字符串中的内容,它应该像和那样做什么?

针对这些问题,C中有两个经典的解决方案,即引用计数和写时复制。

在引用计数中,每个对象负责维护该对象的所有引用的计数值。当一个新的引用指向一个对象时,引用计数器递增,当一个引用被移除时,引用计数器递减。当引用计数达到零时,对象将释放被占用的资源。

以下是具有引用计数的封装类:

类别引用计数

{

公共:

ref count():count _(new int(1)){ };

RefCount(const RefCount other):count _(other . count _)

{

* count _;

}

~RefCount()

{

if ( - *count_==0)

{

删除计数_;

count _=nullptr

}

}

仅限布尔()

{

return * count _==1;

}

void重附属(const RefCount other)

{

//更新原始引用计数的信息

if(仅())

{

删除计数_;

}

其他

{

-* count _;

}

//更新新引用计数的信息

* other . count _;

//绑定到新的引用计数

count _=other.count _

}

void MakeNewRef()

{

if (*count_ 1)

{

-* count _;

count _=new int(1);

}

}

私人:

int * count _;

};

文案:写的时候抄。通过复制初始化对象时,参数的资源不会直接复制到新对象中。当需要修改这些资源时,先复制原始资源,然后再进行修改,这样就避免了不必要的内存复制。

下面的代码是完整的句柄类MyStringHandle。每个handle类都包含一个引用计数类,用于管理和记录对MyString对象的引用数量。

MyStringHandle类

{

公共:

MyStringHandle() : pstr_(新的MyString){}

//这两个参数的构造函数必须构造一个新的MyString对象。

MyString handle(const char * str):pstr _(new MyString(str)){ }

MyString handle(const MyString other):pstr _(new MyString(other)){ }

//复制构造函数,将指针绑定到参数绑定的对象,直接复制引用计数,更新复制构造函数中引用计数的相关信息。

MyStringHandle(const MyStringHandle ohter):ref _ count _(ohter . ref _ count _),pstr_(ohter.pstr_) {}

~MyStringHandle()

{

if (ref_count_。仅())

{

删除pstr _;

pstr _=nullptr

}

}

MyStringHandle运算符=(const MyStringHandle other)

{

//绑定到同一个对象的句柄不经处理就相互赋值。

if (other.pstr_==pstr_)

{

返回* this

}

//如果当前引用是唯一的,销毁当前引用的MyString。

if (ref_count_。仅())

{

删除pstr _;

}

//分别重定向引用计数和对象指针

ref_count_。重新挂接(other . ref _ count _);

pstr _=other.pstr _

返回* this

}

//str='abc '这涉及到字符串内容的修改,

MyStringHandle运算符=(const char* str)

{

if (ref_count_。仅())

{

//如果当前句柄是对MyString对象的唯一引用,直接改变对象进行赋值。

* pstr _=str

}

其他

{

//如果不是唯一引用,创建一个新的引用,用原来的引用号-1构造一个新的MyString对象。

ref_count_。make new ref();

pstr_=新的MyString(str);

}

返回* this

}

私人:

MyString * pstr _;

RefCount ref _ count _

};

看一个测试程序:

int _tmain(int argc,_TCHAR* argv[])

{

//构造MyString

MyStringHandle str 1(' hello ~ ~ ');

//不会构造新的MyString

MyStringHandle str2=str1

MyStringHandle str3=str1

MyStringHandle str4=str1

//构造一个空的MyString

MyStringHandle str5

//将str1赋给str5,不会有内存复制

str5=str1

//修改str5的值

str5=' 123

str5=' 456

返回0;

}

摘要

介绍了C handle类的设计思想和简单实现,主要通过引用计数和写时复制来实现。这两个思路还是很经典的,垃圾回收和智能指针可以借鉴。水平有限,可能会有一些错误或者描述不清。欢迎拍砖~ ~

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • 详解c语言中的字符串数组是什么,详解c语言中的字符串数组结构,详解C语言中的字符串数组
  • 表达式求值c++实现,c语言实现表达式求值
  • 看懂c语言基本语法,C语言详解,C语言的基本语法详解
  • 用c语言实现快速排序算法,排序算法设计与实现快速排序C语言,C语言实现快速排序算法实例
  • 深入解析c语言中函数指针的定义与使用方法,深入解析c语言中函数指针的定义与使用情况,深入解析C语言中函数指针的定义与使用
  • 描述E-R图,E-R图举例,关于C语言中E-R图的详解
  • 折半查找法C语言,折半查找算法(算法设计题)
  • 折半查找法C语言,c语言折半法查找数据,C语言实现折半查找法(二分法)
  • 扫雷小游戏c++代码设计,c语言扫雷游戏源代码,C语言实现扫雷小游戏详细代码
  • 怎样统计程序代码行数,C语言统计行数,C#程序员统计自己的代码行数
  • 基于c语言的贪吃蛇游戏程序设计,用c语言编写贪吃蛇游戏程序,C语言实现简单的贪吃蛇游戏
  • 图的两种遍历算法,图的遍历算法代码c语言,Python算法之图的遍历
  • 留言与评论(共有 条评论)
       
    验证码: