天天看点

C++中字符串类String的一些函数

C++中字符串String的一些函数原型

class String{
	…
	private:
		char * m_data;
}
           

c++编译器会自动为一个类产生四个缺省的函数,如:无参的构造函数,拷贝构造函数,析构函数,赋值函数。

字符串拷贝函数strcpy的原型:

char *strcpy(char *strDest, const char *strSrc){
	char *strTmp = strDest;
	while((*strDest++ = *strSrc++) !=’\0’){
		;
	}
	return strTmp;		
}
           

析构函数:

String::~String(void){
	delete []m_data;
}
           

构造函数:

String::String(const char *str){
	if(str == NULL){
		m_data = new char[1];
		*m_data = ‘\0’;
	}else{
		m_data = new char[strlen(str) +1];
		strcpy(m_data, str);
	}
}	
           

缺省的拷贝构造函数,缺省的赋值函数都是采用“位拷贝”,而非“值拷贝”的方式实现,如果类中含有指针变量,这两个函数都会出错,因为“位拷贝”拷贝的是地址(是memorycopy),实际需要的可能是拷贝内容的“值拷贝”(strcpy)。

以String类型来说,把str2赋值给str1,“位拷贝”意味着执行str1.m_data=str2.m_data;这里会有三个问题:1)str1.m_data原有的内存没有被释放,造成内存泄露;2)str1.m_data和str2.m_data指向同一块内存,所以一个变动会影响另一个;3)在对象被析构时,m_data会被释放两次。

拷贝构造函数是在对象被创建时调用的,而赋值函数只能被已经存在了的对象调用,如:

String str1(“abc”);
String str2(“123”);
String str3 = str1;//这里调用了拷贝构造函数,跟String str3(str1);写法相同。
str3 = str2;//这里调用了赋值函数  
           

拷贝构造函数:

String::String(const String &other){
	int length = strlen(other.m_data);
	m_data = new char[length +1];
	strcpy(m_data, other.m_data);
}
           

重载的赋值函数operate= 的原型:

String & String::operate=(const String &other){
	//先判断自赋值
	if(this == &other)
		return *this;
	//释放了原来的内存资源,也就无法做自己赋值给自己的操作了,所以前面要做自赋值判断。
	delete []m_data;
	m_data= new char[strlen(other.m_data)+];
	strcpy(m_data, other.m_data);
	return *this;
}
           

赋值函数的返回值类型是引用,返回*this的引用,不需要拷贝过程;如果用“值传递”,也就是说如果返回类型是值类型,功能没有问题,但是因为return语句要把*this拷贝到保存返回值的外部存储单元中,增加了不必要的开销,降低了赋值函数的效率。

重载String的相加函数operate+ 的实现:

String operate+(const String &s1, const String &s2){
	String temp;
	delete []temp.m_data;
	temp.m_data = new char[strlen(s1.m_data)+strlen(s2.m_data)+1];
	strcpy(temp.m_data, s1.m_data);
	strcat(temp.m_data, s2.m_data);
	return temp;
}
           

相加函数的返回值类型是值类型,如果使用“引用传递”,也就是返回值改为引用类型,功能就无法实现了,因为函数返回的是一个指向局部对象变量temp的引用,函数内的局部变量的存储单元是在栈空间的,由于temp在函数结束时被自动销毁,所以导致返回的引用无效了。

继续阅读