c++中string类的基本功能的实现(1)
2016-05-29 17:22
615 查看
1、传统的实现string类的方法
优点:程序简单易懂
缺点:
1)在实现其拷贝构造和赋值的操作时多次的调用new动态的开辟空间,因此也需要多次的通过delete来释放空间。如果处理不当还容易造成内存泄漏。
2)程序的一致性比较差
优点:程序简单易懂
缺点:
1)在实现其拷贝构造和赋值的操作时多次的调用new动态的开辟空间,因此也需要多次的通过delete来释放空间。如果处理不当还容易造成内存泄漏。
2)程序的一致性比较差
2、现代的实现string类的方法写实 拷贝构造实现思路: a)创建一个临时对象,并通过cconst String._str来构造。 b)构造完成之后将临时对象的_str和this._str进行交换进而使得对象的内容交换来完成拷贝构造 赋值实现思路: 通过参数的值传递来构造对象,并将对象的内容交换 优点: 1)程序的一致性比较好 2)只是在构造函数中出现了开辟空间的new,只在析构函数中出现了delete结构清晰,不容易造成内存泄漏class String { public: // 构造函数 String(char *str = "") :_str(new char [strlen(str)+1]) { if (_str != NULL) { strcpy(_str, str); } } //拷贝构造 String(const String& str) :_str(NULL)//防止其指向一份不合法的空间 { String tmp(str._str); swap(_str, tmp._str); } //赋值 String& operator =(String str) { swap(_str, str._str); return *this; } //析构函数 ~String() { delete [] _str; } private: char * _str; };
3、写实函数提高string类的效率
在以上的两种string类的实现方法中,都存在一个效率的问题。有的时候字符串比较长,而且对象建立之后也不一定更改。但是以上两种方法无论何时都需要构建,其效率比较低而且会带来内存的浪费。
我们可以通过让所有指向相同字符串内容的对象指向同一份空间,通过计数器来记录对象的个数,避免析构出现错误。
所以可以通过在开辟对象的时候多开辟4个字节的空间,来存放计数器。如果修改的时候再开辟空间。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <string>
using namespace std;
class String
{
public:
//构造函数
String(char *str="")
:_Pstr(FindStartRef(new char[strlen(str)+1+sizeof(int)]))
{
*Count(_Pstr) = 1;//计数器
strcpy(_Pstr, str);//将字符串拷贝
}
//拷贝构造函数
//如果不更改对象的内容则让多个对象的字符指针指向同一份空间
String(const String& s)
{
_Pstr = s._Pstr;
(*Count(_Pstr))++;//计数器加1
}
//赋值语句
//如果不更改对象的内容则让多个对象的字符指针指向同一份空间
String& operator =(const String& s)
{
if (this != &s)//避免自赋值
{
if (--*(Count(_Pstr)) == 0)
{
delete[]FindDel(_Pstr);
}//只有一个对象使用的一份空间则释放
else
{
_Pstr = s._Pstr;
(*Count(_Pstr))++;
}
}
return *this;
}
//析构函数
~String()
{
if (--*(Count(_Pstr)) == 0)
{
delete[]FindDel(_Pstr);
}
}
public:
//找到开辟空间时的存放字符串的首地址
char * FindStartRef(char* str)
{
return (str + 4);
}
//找到释放空间时的首地址
char * FindDel(char* del)
{
return (del - 4);
}
//找到计数器的首地址
int *Count(char* str)
{
return (int *)(str - 4);
}
public:
//修改写实对象的内容函数
char & operator[](int index)
{
if (--*(Count(_Pstr)) != 0)
{
char * tmp = _Pstr;
_Pstr = FindStartRef(new char[strlen(_Pstr) + 1 + sizeof(int)]);
*Count(_Pstr) = 1;//计数器置1
strcpy(_Pstr, tmp);
}//如果该对象和其他对象公用一份空间
else
{
//单独使用一份空间可以随意更改
}
return _Pstr[index];
}
private:
char * _Pstr;
};
相关文章推荐
- c/c++单链表面试题—链表带环问题
- c/c++单链表面试题—链表相交问题
- c++实现双向链表的常用功能
- 函数模板在c++动态顺序表中的大作用
- c++智能指针的不断演化
- 用C语言输出9*9乘法表
- C语言中移位、逻辑运算符的简单应用
- 用C语言实现“智障”的棋盘游戏
- C++浅析函数指针
- C++ map 中的reverse_iterator
- [c++] vector的使用
- c++流常见操作
- C++的链接错误LNK2005总结
- C++基础<04>—标准库vector类型
- 用C++实现WebGIS
- C语言学习入们到精通之学习笔记(二)
- C++第14周项目模板【项目3-数组类模板】
- 栈的实现 -- 顺序栈和链式栈(C++描述)
- C/C++内存管理详解 堆 栈
- c++ 虚析构函数的作用分析