已知 String 类的原型为:
class String
{
public:
String (const char* str = NULL); // 普通构造函数
String (const String &other); // 拷贝构造函数
~String(void); // 析构函数
String & operater = (const String &other); // 赋值函数
private:
char* m_data;
};
编写 String 类的以上4个函数。
实现构造函数就是根据传入的字符串的长度申请一段内存,存储这个传入的字符串的值,当字符串为空时,字符串的长度为1,内容为 '\0';析构函数就是直接释放成员指针 m_data 所指向的内存空间;因为类 string 含有成员指针变量,所以拷贝构造函数要实现的是深拷贝;实现赋值运算符时要注意以下几点:
- 判断是不是对象自身赋值,是则直接返回当前对象。
- 释放原有的指针指向的内存资源。
- 申请新的内存空间,用源对象初始化这段空间。
- 返回本对象的引用。
SString::SString(const char* str) // 普通构造函数
{
int length = strlen(str);
m_data = new char[length + 1];
strcpy(m_data, str);
}
SString::SString(const SString &other) // 拷贝构造函数
{
int length = strlen(other.m_data);
m_data = new char[length + 1];
strcpy(m_data, other.m_data);
}
SString::~SString(void) // 析构函数
{
delete[] m_data;
}
SString & SString::operater = (const SString &other) // 赋值函数
{
if (this == &other) // 检查自赋值
return *this;
if (m_data != NULL) // 释放原有的内存资源
delete[] m_data;
int length = strlen(other.m_data);
m_data = new char[length + 1];
if (m_data != NULL)
strcpy(m_data, other.m_data);
return *this;
}
拷贝构造函数和赋值函数很相似,两者都可以用同一个类对象初始化另一个对象;但是,两者在初始化方式上还是有不同之处。
- 拷贝构造函数生成新的类对象,而赋值运算不能。
- 由于拷贝构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验原对象是否和新建对象相同。而赋值运算则需要这个操作;此外,如果赋值运算中原来的对象有内存分配,要先把内存释放掉。