面试题答案
一键面试生命周期管理策略
- 智能指针的使用:由于
T1
和T2
可能相互包含,使用原始指针很容易导致悬空指针和内存泄漏。因此,应使用智能指针(如std::unique_ptr
或std::shared_ptr
)来管理对象的生命周期。std::unique_ptr
:适用于对象所有权唯一的情况,当std::unique_ptr
被销毁时,它所指向的对象也会被销毁。std::shared_ptr
:适用于多个对象可以共享同一个对象所有权的情况,通过引用计数来管理对象的生命周期,当引用计数为0时,对象被销毁。
- 构造和析构顺序:在构造
T1
和T2
对象时,要确保它们内部的成员对象(或指针所指向的对象)在需要时已经被正确构造。在析构时,要保证成员对象(或指针所指向的对象)在自身被销毁前已经被正确销毁。 - 避免循环引用:如果使用
std::shared_ptr
,要特别注意避免循环引用。循环引用会导致对象的引用计数永远不会为0,从而造成内存泄漏。可以使用std::weak_ptr
来打破循环引用。std::weak_ptr
不增加对象的引用计数,它可以观察std::shared_ptr
所管理的对象,但不会阻止对象被销毁。
示例代码框架
#include <iostream>
#include <memory>
// 前向声明
class T2;
class T1 {
public:
// 使用std::unique_ptr管理T2对象
std::unique_ptr<T2> t2Ptr;
T1() {
std::cout << "T1 constructed" << std::endl;
}
~T1() {
std::cout << "T1 destructed" << std::endl;
}
};
class T2 {
public:
// 使用std::weak_ptr避免循环引用
std::weak_ptr<T1> t1WeakPtr;
T2() {
std::cout << "T2 constructed" << std::endl;
}
~T2() {
std::cout << "T2 destructed" << std::endl;
}
};
template<typename T1, typename T2>
void complexOperation(T1 t1, T2 t2) {
// 这里可以进行复杂操作
std::cout << "Complex operation on T1 and T2" << std::endl;
}
int main() {
// 创建T1和T2对象
std::shared_ptr<T1> t1 = std::make_shared<T1>();
std::shared_ptr<T2> t2 = std::make_shared<T2>();
// 设置相互关系
t1->t2Ptr = std::make_unique<T2>();
t2->t1WeakPtr = t1;
// 调用函数模板
complexOperation(*t1, *t2);
return 0;
}
在这个示例中:
T1
类使用std::unique_ptr
来管理T2
对象,确保T1
对象销毁时,其包含的T2
对象也会被正确销毁。T2
类使用std::weak_ptr
来指向T1
对象,避免了循环引用,确保对象能够被正确销毁。main
函数中创建了T1
和T2
的std::shared_ptr
对象,并设置了它们之间的相互关系,然后调用complexOperation
函数模板。