在谭浩强先生的书里看到的,书上说这样的对象在赋值时会产生严重的后果,是因为动态分配的特殊性吗?
在定义类的时候不能对成员变量赋值,因为类只是一种 数据类型或者说是一种模板,本身不占用内存空间,而变量的值则需要内存来存储。
成员变量只用于声明,而不负责分配内存。
把谭老师书中的描述上下文贴出来看看。到底说的是什么事。是不建议类的成员变量用动态分配空间吗?还是别的意思
按字面理解,因该是类包含指针变量吧!
例如:
class A {
public:
A () { data = (char *)malloc(1024); // 动态分配内存 }
~A() { if (data) free(data); //释放内存 }
private:
char *data; // 指针变量,需要动态分配内存
}
如果是这样,类在赋值时确实是会出现一些问题,例如该指针变量是浅拷贝,也就是被赋值的对象的指针变量与当前对象指向同一块内存。(释放内存时会导致程序崩溃...)
例如:
int main(void) {
A a1;
A a2 = a1; // a1的data和a2的data指向同一块内此地址
return 0;
// 程序结束时,类会调用各自的析构函数去释放data指针内存,此时可能会导致程序崩溃
// 两个指针指向同一块内存,当a1的释放了,那么data的内存就是NULL,a2再进行释放的话,就是释放了NULL内存,导致崩溃。
}
该如何解决这样的问题呢?
重新实现赋值构造函数即可。
例如:
class A {
public:
A () { data = (char *)malloc(1024); }
~A() { if (data) free(data); }
// 赋值运算符
A &operator=(const A &a) {
if (data) {
free(data);
}
// 深拷贝,两块内存地址不知想同一块内存
this->data= (char *)malloc(1024);
strcpy_s(this->data, strlen(a.data)+1, a.data);
}
private:
char *data;
}
然后,再进行像同样的赋值操作,程序结束后,就不会崩溃了。各自释放各自的内存,互不干扰。
int main(void) {
A a1;
A a2 = a1; // 赋值时,自动调用赋值构造函数,两个指针不是指向同一个内存地址
return 0;
// 程序结束时,类会调用各自的析构函数去释放data指针内存,无不干扰,程序结束!
}