• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > C++中sting类的简单实现方法

C++中sting类的简单实现方法

作者:chentingting的小天地 字体:[增加 减小] 来源:互联网 时间:2017-05-28

chentingting的小天地 通过本文主要向大家介绍了sting类,sting聚类算法,sting聚类,sting,wwesting斯丁等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

String

在C++的学习生涯我中发现String类的功能十分强大,所以我们是很有必要模拟实现它的,况且在面试的时候模拟实现一个String类也是面试官经常会考的,但是因为外界因素的限制我们是不可能模拟的和库里的string一致的(C++库里的string功能更强大),所以今天我们只模拟实现string的基本功能-构造函数,拷贝构造函数,析构函数,赋值运算符重载,运算符+=的重载,运算符[]的重载,c_str(得到一个C风格的字符指针,可操作字符串),Size,Push_Back,Insert(深拷贝),以及用写时拷贝copy_on_write的方式实现基本的String类

深拷贝的方式

class String 
{ 
friend ostream &operator<<(ostream &os,String &s); 
public: 
String(const char *str=""); //全缺省的构造函数,解决空字符串的问题 
String(const String &ps); //深拷贝 
String &operator=(String s); 
String &operator+=(const char * s); 
const char *C_Str()const //得到C风格的字符指针 
{ 
return _pstr; 
} 
char &operator[](size_t index) 
{ 
return _pstr[index]; 
} 
size_t Size()const 
{ 
return _size; 
} 
void PushBack(char c); 
String &Insert(size_t pos,const char *str); 
//String &operator=(String &s) 
//{ 
// cout<<"String &operator=(String &s)"<<endl; 
// if(this != &s) 
// { 
// delete[]_pstr; 
// _pstr=new char[strlen(s._pstr)+1]; 
// strcpy(_pstr,s._pstr); 
// } 
// return *this; 
//} 
~String() 
{ 
cout<<"~String()"<<endl; 
if(_pstr != NULL) 
{ 
delete[]_pstr; 
_pstr=NULL; 
_size=0; 
_capacity=0; 
} 
} 
private: 
void CheckCapacity(int count); 
private: 
int _size; 
int _capacity; 
char *_pstr; 
}; 
ostream &operator<<(ostream &os,String &s) 
{ 
os<<s._pstr; 
return os; 
} 
String::String(const char *str) 
:_size(strlen(str)) 
,_capacity(strlen(str)+1) 
,_pstr(new char[_capacity]) 
{ 
cout<<"String()"<<endl; 
strcpy(_pstr,str); 
} 
String::String(const String &ps) 
:_size(ps._size) 
,_capacity(strlen(ps._pstr)+1) 
,_pstr(new char[_capacity]) 
{ 
cout<<"String(const String &ps)"<<endl; 
strcpy(_pstr,ps._pstr); 
} 
String &String::operator=(String s) 
{ 
cout<<"String &operator=(String s)"<<endl; 
std::swap(_pstr,s._pstr); 
std::swap(_size,s._size); 
std::swap(_capacity,s._capacity); 
return *this; 
} 
void String::CheckCapacity(int count) 
{ 
if(_size+count >= _capacity) 
{ 
int _count=(2*_capacity)>(_capacity+count)?(2*_capacity):(_capacity+count); 
char *tmp=new char[_count]; 
strcpy(tmp,_pstr); 
delete[]_pstr; 
_pstr=tmp; 
_capacity=_count; 
} 
} 
void String::PushBack(char c) 
{ 
CheckCapacity(1); 
_pstr[_size++]=c; 
_pstr[_size]='\0'; 
} 
String &String::operator+=(const char * s) 
{ 
CheckCapacity(strlen(s)); 
while(*s) 
{ 
_pstr[_size++]=*s; 
s++; 
} 
_pstr[_size]='\0'; 
return *this; 
} 
String &String::Insert(size_t pos,const char *str) 
{ 
char *tmp=new char[strlen(_pstr+pos)]; 
strcpy(tmp,_pstr+pos); 
CheckCapacity(strlen(str)); 
while(*str) 
{ 
_pstr[pos++]=*str; 
str++; 
} 
strcpy(_pstr+pos,tmp); 
return *this; 
}
</div>

通过测试上述代码可正常运行,特别是在实现赋值运算符重载的时候我们使用了两种方式,值得一提的是应用swap函数来实现赋值运算符的重载(在传参时不可以传引用),因为应用swap函数实现是根据临时变量的创建并且该临时变量出作用域就会自动调用析构函数销毁(现代的方法)

测试深拷贝的方法

void text1() 
{ 
String str1("hello"); 
String str2(str1); 
String str3; 
str3=str1; 
cout<<str1<<endl; 
cout<<str2<<endl; 
cout<<str3<<endl; 
cout<<strlen(str1.C_Str())<<endl; //5 
str1[4]='w'; 
cout<<str1<<endl; //hellw 
} 
void text2() 
{ 
String str1("abcd"); 
cout<<str1<<endl; 
str1.PushBack('e'); 
str1.PushBack('f'); 
str1.PushBack('g'); 
str1.PushBack('h'); 
str1.PushBack('i'); 
cout<<str1<<endl; 
cout<<str1.Size()<<endl; 
} 
void text3() 
{ 
String str1("hello"); 
String str2("hello world"); 
String str3(str2); 
str1+=" "; 
str1+="world"; 
cout<<str1<<endl; 
str2.Insert(6," abc "); 
cout<<str2<<endl; 
}
</div>

实现了深拷贝的方法那仫有没有更加高效的方法呢?当然,那就是写时拷贝,我们发现在上述深拷贝的版本里实现的拷贝构造函数又为新的对象重新开辟空间(防止浅拷贝的后遗症:浅拷贝是值拷贝使得两个指针指向同一块空间,在析构该空间时对同一块空间释放多次就会出现问题),那仫如果我们继承了浅拷贝的后遗症-就让多个指针指向同一块空间,此时我们只需要设置一个指针变量让它记录指向这块空间的指针个数,在析构时只要该指针变量的内容为1我们就释放这块空间否则就让计数器减1,这就是写时拷贝的主要思想,下面就让我们用写时拷贝的方法实现一个简单的String类吧

写时拷贝的方法

//写时拷贝的方式 
class String 
{ 
friend ostream& operator<<(ostream & os,String &s); 
public: 
String(const char *str="") 
:_str(new char[strlen(str)+1+4]) 
{ 
cout<<"构造"<<endl; 
_str+=4; 
*((int *)(_str-4))=1; 
strcpy(_str,str); 
} 
String(String &s) 
{ 
cout<<"拷贝构造"<<endl; 
++*((int *)(s._str-4)); 
_str=s._str; 
} 
String &operator=(const String &s) 
{ 
cout<<"赋值语句"<<endl; 
if(--*(int *)(_str-4) == 0) 
{ 
delete[](_str-4); 
} 
++(*(int *)(s._str-4)); 
_str=s._str; 
return *this; 
} 
char &operator[](int index) //写时拷贝 
{ 
assert(index >= 0 && index < (int)strlen(_str)); 
if(*(int *)(_str-4) > 1) 
{ 
--*(int *)(_str-4); 
char *tmp=new char[strlen(_str)+5]; 
strcpy(tmp+4,_str); 
delete[](_str-4); 
_str=tmp+4; 
*(int *)(_str-4)=1; 
} 
return _str[index]; 
} 
~String() 
{ 
cout<<"析构"<<endl; 
if(--*(int *)(_str-4) == 0) 
{ 
cout<<"释放"<<endl; 
delete[](_str-4); 
} 
} 
private: 
char *_str; 
}; 
ostream& operator<<(ostream &os,String &s) 
{ 
os<<s._str; 
return os; 
}
</div>

在这里我们将指针指向的计数器的位置放置在数据空间的前四个字节处

测试用例:

void test1() 
{ 
String str1("abcd"); 
cout<<str1<<endl; 
String str2(str1); 
cout<<str2<<endl; 
String str3; 
str3=str1; 
cout<<str3<<endl; 
} 
void test2() 
{ 
String str1("abcd"); 
cout<<str1<<endl; 
String str2; 
str2=str1; 
cout<<str2<<endl; 
str2[2]='w'; 
cout<<str2<<endl; 
}
</div>

以上所述是小编给大家介绍的C++中sting类的简单实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C++中sting类的简单实现方法

相关文章

  • 2017-05-28c语言指针之二级指针示例
  • 2017-05-28C语言中时间的基本用法小结
  • 2017-05-28C++之类的静态变量
  • 2017-05-28C语言中的sizeof操作符用法及和strlen的区别
  • 2017-05-28如何解决C语言,函数名与宏冲突
  • 2017-05-28C语言读取文件流的相关函数用法简介
  • 2017-05-28C++进程共享数据封装成类实例
  • 2017-05-28C++中Boost库裁剪与其应用详解
  • 2017-05-28VC++创建msi文件的方法
  • 2017-05-28字典树的基本知识及使用C语言的相关实现

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C++ 头文件系列(set)详解
    • C语言结构体数组详解(带实例演示)
    • 数据结构之位图(bitmap)详解
    • 哪款C语言编译器(IDE)适合初学者?
    • 深入Main函数中的参数argc,argv的使用详解
    • 深入理解C++中的vector类的用法及特性
    • 解析c++中参数对象与局部对象的析构顺序的详解
    • C++获取本机登陆过的QQ号码示例程序
    • 关于C语言指针赋值的问题详解
    • 应用程序操作NorFlash示例代码分享(norflash接口使用方法)

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有