面试题答案
一键面试1. 当T为自定义类类型
- 生命周期影响:当调用
process(obj)
时,obj
的生命周期不受process
函数内对ref
操作的直接影响。ref
是obj
的引用,在process
函数内对ref
的操作,比如修改其成员变量等,是直接作用于obj
本身。当process
函数结束,obj
的生命周期不会结束,只有当obj
所在作用域结束时,obj
才会被销毁,调用其析构函数释放动态分配的资源。 - 资源管理问题:如果在
process
函数内对ref
进行操作导致异常抛出,而此时obj
中部分资源已经被修改,可能会导致资源泄漏。例如,假设自定义类MyClass
在构造函数中分配了内存,在process
函数中先修改了内存中的数据,然后在后续操作中抛出异常,此时MyClass
的析构函数可能无法正确释放内存。 - 解决方案:使用RAII(Resource Acquisition Is Initialization)原则。在自定义类的构造函数中获取资源,析构函数中释放资源。在
process
函数内,任何可能抛出异常的操作都应该保证在异常发生时,已经获取的资源能正确释放。例如,可以使用智能指针来管理资源,这样即使异常抛出,智能指针的析构函数也会自动释放资源。
2. 当T为指向自定义类对象的智能指针类型
- 生命周期影响:如果
T
是智能指针类型(如std::unique_ptr
或std::shared_ptr
),调用process(obj)
时,obj
作为智能指针,其生命周期依然遵循智能指针的规则。当process
函数结束,若obj
是函数参数传入的局部智能指针,它会被销毁。对于std::unique_ptr
,会释放所指向的对象;对于std::shared_ptr
,如果引用计数降为0,也会释放所指向的对象。在process
函数内对ref
(智能指针引用)的操作,比如重置智能指针(ref.reset()
),会影响所指向对象的生命周期。如果ref
是最后一个指向对象的智能指针,那么对象会被释放。 - 资源管理问题:如果在
process
函数内意外地重置了ref
(智能指针引用),而外部代码还期望通过原智能指针访问对象,就会导致悬空指针问题。例如,调用process
函数前,有其他代码依赖obj
指向的对象,而在process
函数内执行ref.reset()
,那么外部代码再使用obj
时就会出错。 - 解决方案:对于
std::unique_ptr
,在函数内操作时要谨慎重置,除非明确知道外部不再需要该指针。对于std::shared_ptr
,要确保理解引用计数的变化情况。可以在函数内创建临时的std::weak_ptr
来观察对象是否存在,而不增加引用计数,避免意外释放对象。同时,在函数接口设计上,可以通过文档清晰说明函数对传入智能指针的操作方式,让调用者清楚可能的风险。