面试题答案
一键面试1. 可能出现的内存管理问题
- 对象创建(默认构造函数):
- 问题:若默认构造函数没有初始化指针成员指向的动态内存,使用该对象时可能导致未定义行为,因为指针处于未初始化状态。
- 对象拷贝(拷贝构造函数):
- 问题:编译器自动生成的拷贝构造函数执行浅拷贝,即仅仅复制指针的值,而非动态分配的内存内容。这意味着多个对象将指向同一块内存,当其中一个对象销毁这块内存时,其他对象的指针就成为野指针,再次访问会导致未定义行为。
- 对象赋值(赋值运算符重载):
- 问题:自动生成的赋值运算符重载同样执行浅拷贝,和拷贝构造函数类似,会造成多个对象指向同一块动态内存,并且在释放内存时会产生重复释放的问题,导致程序崩溃。
- 对象销毁(析构函数):
- 问题:自动生成的析构函数不会释放指针成员指向的动态内存,从而导致内存泄漏,因为动态分配的内存没有被释放。
2. 手动实现这些函数来解决问题
- 默认构造函数:
class MyClass {
private:
int* data;
public:
MyClass() {
data = new int;
*data = 0; // 初始化数据
}
};
- 拷贝构造函数:
class MyClass {
private:
int* data;
public:
MyClass(const MyClass& other) {
data = new int;
*data = *other.data; // 深拷贝,分配新内存并复制内容
}
};
- 赋值运算符重载:
class MyClass {
private:
int* data;
public:
MyClass& operator=(const MyClass& other) {
if (this != &other) {
delete data;
data = new int;
*data = *other.data; // 释放原有内存,分配新内存并复制内容
}
return *this;
}
};
- 析构函数:
class MyClass {
private:
int* data;
public:
~MyClass() {
delete data; // 释放动态分配的内存
}
};
通过手动实现上述四个函数,分别在对象创建时正确初始化动态内存,拷贝和赋值时执行深拷贝,销毁时释放动态内存,从而解决自动生成的缺省函数带来的内存管理问题。