面试题答案
一键面试智能指针
- 优势:
- 自动内存管理:智能指针利用RAII(Resource Acquisition Is Initialization)机制,在对象生命周期结束时自动释放所指向的内存,无需手动调用
delete
,极大减少了内存泄漏的风险。例如std::unique_ptr<int> ptr(new int(10));
,当ptr
超出作用域时,所指向的int
对象内存会自动释放。 - 异常安全:在发生异常时,智能指针能保证已分配的资源被正确释放,避免资源泄漏。例如在函数中使用智能指针,如果函数中途抛出异常,智能指针会在析构时释放资源。
- 简化代码:无需手动跟踪内存的分配和释放,使代码更简洁,可读性更高。
- 自动内存管理:智能指针利用RAII(Resource Acquisition Is Initialization)机制,在对象生命周期结束时自动释放所指向的内存,无需手动调用
- 不足:
- 性能开销:智能指针内部包含引用计数(如
std::shared_ptr
)或其他管理机制,会带来一定的性能开销,虽然通常较小,但在对性能要求极高的场景下可能成为问题。 - 循环引用:
std::shared_ptr
可能会出现循环引用问题,导致内存无法释放。例如两个类中都使用std::shared_ptr
互相指向对方,形成循环引用,需要使用std::weak_ptr
来解决。
- 性能开销:智能指针内部包含引用计数(如
指针使用后置空操作
- 优势:
- 简单直接:操作简单,只需在
delete
指针后将指针赋值为nullptr
,如int* p = new int(10); delete p; p = nullptr;
,防止指针成为野指针。 - 无额外开销:不引入额外的性能开销,仅增加了简单的赋值操作。
- 简单直接:操作简单,只需在
- 不足:
- 手动管理:需要开发者手动进行内存释放和指针置空操作,增加了出错的可能性,容易忘记
delete
或置空,导致内存泄漏或野指针问题。 - 异常不安全:如果在
delete
之后、置空之前抛出异常,指针仍可能成为野指针。
- 手动管理:需要开发者手动进行内存释放和指针置空操作,增加了出错的可能性,容易忘记
两者结合使用
- 可以结合使用:
- 在实际项目中,对于一些简单的、对性能敏感且代码逻辑清晰的场景,可以在手动管理内存的指针使用后置空操作。例如在一些底层库中,对性能要求极高,且代码结构简单,手动管理内存并置空指针可避免智能指针的性能开销。
- 对于复杂的对象层次结构、涉及动态内存分配和释放频繁的场景,优先使用智能指针。当需要从智能指针获取原始指针传递给一些不支持智能指针的API时,在使用完原始指针后,可以将其置空。例如:
std::unique_ptr<int> smartPtr(new int(10));
int* rawPtr = smartPtr.get();
// 使用rawPtr调用不支持智能指针的API
// 使用完后
rawPtr = nullptr;
这样结合可以在不同场景发挥两者的优势,减少野指针和内存泄漏的风险。