面试题答案
一键面试1. 使用默认拷贝构造函数和默认赋值运算符重载函数可能出现的内存管理问题及原因
- 内存泄漏:默认拷贝构造函数只是简单地按位拷贝成员变量。对于
Resource
类,这意味着buffer
指针会被拷贝,而不是其指向的内存。当两个Resource
对象都指向同一块内存,且其中一个对象被销毁时,这块内存会被释放。如果另一个对象还试图访问这块已释放的内存,就会导致未定义行为。并且,如果每个对象都尝试释放这块内存(例如在析构函数中),就会出现重复释放,导致内存泄漏。 - 悬空指针:在默认赋值运算符重载函数中,同样只是简单地按位赋值成员变量。如果目标对象之前已经分配了内存,这块内存不会被正确释放,从而导致内存泄漏。而且,新赋值的
buffer
指针指向的内存与源对象指向的内存相同,当源对象被销毁,释放了这块内存后,目标对象的buffer
就成为了悬空指针,再次访问会导致未定义行为。
2. 自定义缺省函数避免这些问题的方法
- 自定义拷贝构造函数:
Resource::Resource(const Resource& other) {
size = other.size;
buffer = new char[size];
std::copy(other.buffer, other.buffer + size, buffer);
}
此拷贝构造函数为新对象分配了独立的内存,并将源对象buffer
中的内容复制到新分配的内存中,避免了内存共享带来的问题。
- 自定义赋值运算符重载函数:
Resource& Resource::operator=(const Resource& other) {
if (this != &other) {
delete[] buffer;
size = other.size;
buffer = new char[size];
std::copy(other.buffer, other.buffer + size, buffer);
}
return *this;
}
在自定义赋值运算符重载函数中,首先检查是否是自我赋值。如果不是,先释放目标对象已分配的内存,然后重新分配内存并复制源对象的内容,从而避免内存泄漏和悬空指针问题。