c++中string类的基本功能的实现(1)

1、传统的实现string类的方法

优点:程序简单易懂

缺点:

1)在实现其拷贝构造和赋值的操作时多次的调用new动态的开辟空间,因此也需要多次的通过delete来释放空间。如果处理不当还容易造成内存泄漏。

2)程序的一致性比较差

#include <iostream>
#include <string>
using namespace std;

class String 
{
public:
	// 构造函数
	String(char *str = "")
		:_str(new char [strlen(str)+1])
	{
		if (_str != NULL)
		{
			strcpy(_str, str);
		}
	}
	//拷贝构造
	String(const String& str)
		:_str(new char[strlen(str._str) + 1])
	{
		if (_str != NULL)
		{
			strcpy(_str, str._str);
		}
	}
	//赋值
	String& operator = (const String& str)
	{
		if (this != &str)//自赋值问题
		{
			delete[]_str;//释放之前开辟的空间
		_str = new char[strlen(str._str) + 1];//开辟新的空间
			strcpy(_str, str._str);//拷贝
		}
		return *this;
	}
	//析构函数
	~String()
	{
		delete [] _str;
	}

private:
	char * _str;
};

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;
};
时间: 2024-12-20 01:19:35

c++中string类的基本功能的实现(1)的相关文章

java11-3 String类的获取功能

package cn_String2;/* String类的获取功能 int length():获取字符串的长度. char charAt(int index):获取指定索引位置的字符 int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引. 为什么这里是int类型,而不是char类型? 原因是:'a'和97其实都可以代表'a' int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引. int indexOf(int ch,int

Java中String类学习总结

java中String类的使用频率非常高,本人在学习此模块时,认为下列几点知识值得注意: 一.String是不可变对象 java.lang.String类使用了final修饰,不能被继承.Java程序中的所有字面值,即双引号括起的字符串,如"abc",都是作为String类的实例实现的.String是常量,其对象一旦构造就不能再被改变.换句话说,String对象是不可变的,每一个看起来会修改String值的方法,实际上都是创造了一个全新的String对象,以包含修改后的字符串内容.而最

【转载】Java中String类的方法及说明

转载自:http://www.cnblogs.com/YSO1983/archive/2009/12/07/1618564.html String : 字符串类型 一.构造函数     String(byte[ ] bytes):通过byte数组构造字符串对象.     String(char[ ] value):通过char数组构造字符串对象.     String(Sting original):构造一个original的副本.即:拷贝一个original.     String(Strin

5.15 String类的获取功能

/*  * String类的获取功能  * int length():获取字符串的长度.  * char charAt(int index):获取指定索引位置的字符  * int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引.  *  为什么这里是int类型,而不是char类型?  *  原因是:'a'和97其实都可以代表'a'  * int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引.  * int indexOf(int

C++面试中string类的一种正确写法

C++ 的一个常见面试题是让你实现一个 String 类,限于时间,不可能要求具备 std::string 的功能,但至少要求能正确管理资源.具体来说: 能像 int 类型那样定义变量,并且支持赋值.复制. 能用作函数的参数类型及返回类型. 能用作标准库容器的元素类型,即 vector/list/deque 的 value_type.(用作 std::map 的 key_type 是更进一步的要求,本文从略). 换言之,你的 String 能让以下代码编译运行通过,并且没有内存方面的错误. vo

java中String类小结

构建一个字符串 1.用字符串直接量: String message = new String("Welcome to java"); 2.用字符串直接量: String message = "Welcome to java"; 3.用字符数组 Char[] charArray = {'m', 'y'}; String message = new String(charArray); 不可变字符与限定字符串 String对象是不可变的,内容不能改变 java虚拟机为了

Java基础知识强化33:String类之String类的判断功能

1. String类的判断功能: boolean equals (Object obj ) boolean equalsIgnoreCase (String str ) boolean contains (String str ) boolean startsWith (String str ) boolean endsWith (String str ) boolean isEmpty() 2. 案例: 1 package cn.itcast_03; 2 3 /* 4 * String类的判断

c++中string类的详解

通过在网站上的资料搜集,得到了很多关于string类用法的文档,通过对这些资料的整理和加入一些自己的代码,就得出了一份比较完整的关于string类函数有哪些和怎样用的文档了!下面先罗列出string类的函数有哪一些,然后再罗列出函数的原型,最后到代码的实现 标准C++中提供的string类得功能也是非常强大的,一般都能满足我们开发项目时使用.现将具体用法的一部分罗列如下,只起一个抛砖引玉的作用吧,好了,废话少说,直接进入正题吧!要想使用标准C++中string类,必须要包含#include <s

Java中String类的方法及说明

String : 字符串类型 一.构造函数     String(byte[ ] bytes):通过byte数组构造字符串对象.     String(char[ ] value):通过char数组构造字符串对象.     String(Sting original):构造一个original的副本.即:拷贝一个original.     String(StringBuffer buffer):通过StringBuffer数组构造字符串对象.  例如:      byte[] b = {'a',