一:拷贝构造函数
1. 浅拷贝:
#include<iostream>
#include<string.h>
using namespace std;
class STRING
{
public:
//此处补充构造函数
STRING() {
str = NULL;
ct = 0;
}
STRING(const char* _str) {
int i = 0;
for (; _str[i]; i++);
ct = i;
str = new char[i + 1];
for (int j = 0; j <= i; j++) {
str[j] = _str[j];
}
}
//此处补充析构函数
~STRING() {
if (str) delete[]str;
}
char* str;//字符指针指向字符串
int ct;//字符串的长度
void show(int t);
};//注意设置show 的参数
void STRING::show(int t = 0) {
if (t == 0) {
cout << this->str << endl;
}
else {
for (int i = 0; i < t; i++) {
cout << this->str[i];
}
cout << endl;
}
}
int main()
{
STRING str;
char str_1[] = "hello world";
STRING str1(str_1);
STRING str2 = str1;
STRING str3("finished");
str1.show(); //输出 str1 字符串
str2.show(3); //输出 str2 前三个字符
str3.show(); //输出 str_3
return 0;
}
运行结果:
系统会报错,原因是这个例子调用的是默认的拷贝构造函数,复制构造函数str2是保存在栈中,栈内存在程序结束后自动释放,而堆内存需要显式释放。str2在系统自动调用中使str1的str指针指向了str2的str指针,可以理解为str2在释放时将str1中的指针所指内存释放了,此时str1的str内存已经不存在了,那么delete就释放了一个已经被释放的内存,则会出现错误。解决方法是写复制构造函数的深拷贝。
2. 深拷贝
我们将成员变量换成指针变量,继续实验。
#include<iostream>
#include<string.h>
using namespace std;
class STRING
{
public:
//此处补充构造函数
STRING() {
str = NULL;
ct = 0;
}
STRING(const char* _str) {
int i = 0;
for (; _str[i]; i++);
ct = i;
str = new char[i + 1];
for (int j = 0; j <= i; j++) {
str[j] = _str[j];
}
}
STRING(const STRING& s) {
str = new char[s.ct + 1];
for (int j = 0; j <= s.ct; j++) {
str[j] = s.str[j];
}
ct = s.ct;
}
//此处补充析构函数
~STRING() {
if (str) delete[]str;
}
char* str;//字符指针指向字符串
int ct;//字符串的长度
void show(int t);
};//注意设置show 的参数
void STRING::show(int t = 0) {
if (t == 0) {
cout << this->str << endl;
}
else {
for (int i = 0; i < t; i++) {
cout << this->str[i];
}
cout << endl;
}
}
int main()
{
STRING str;
char str_1[] = "hello world";
STRING str1(str_1);
STRING str2 = str1;
STRING str3("finished");
str1.show(); //输出 str1 字符串
str2.show(3); //输出 str2 前三个字符
str3.show(); //输出 str_3
return 0;
}
可以看到,程序不报错了。
深拷贝就是给复制构造函数也用new创建内存。
STRING(const STRING& s) {
str = new char[s.ct + 1];
for (int j = 0; j <= s.ct; j++) {
str[j] = s.str[j];
}
ct = s.ct;
}
总结起来就是先开辟出和源对象一样大的内存区域,然后将需要拷贝的数据复制到目标拷贝对象。