广告

C++ 智能指针是否为空如何判断?安全高效的空值判定方法(适用于 unique_ptr 与 shared_ptr)

一、基本原理:如何判断 unique_ptr 与 shared_ptr 是否为空

在 C++ 中,std::unique_ptr 与 std::shared_ptr 提供了一个直观的空值判断入口。核心特性是它们可以在布尔上下文中直接评估,非空时为 true,空时为 false。

对于这两种智能指针,两种常见写法是使用布尔上下文进行判断(如 if (ptr))以及直接与 nullptr 进行比较(如 if (ptr != nullptr))。

如果你需要把智能指针的状态传递给需要原始指针的接口,可以使用 get() 方法获取原始指针,但这也带来生命周期和悬空的风险,因此应谨慎使用。

#include 
#include void demo_unique() {std::unique_ptr uptr; // 空if (uptr) {std::cout << "uptr 非空" << std::endl;} else {std::cout << "uptr 为 nullptr" << std::endl;}// 直接比较if (uptr == nullptr) {// 处理空指针情形}uptr = std::make_unique(42);if (uptr) {std::cout << "*uptr = " << *uptr << std::endl;}// 使用原始指针调用需要 T* 的接口auto raw = uptr.get();if (raw) {std::cout << "raw 指针指向的值: " << *raw << std::endl;}
}

对于 shared_ptr,原理与 unique_ptr 一致,空值判断的语义并无差异,皆以布尔上下文或与 nullptr 的比较来表达。

#include 
#include void demo_shared() {std::shared_ptr sptr; // 空if (sptr) {std::cout << "sptr 非空" << std::endl;} else {std::cout << "sptr 为 nullptr" << std::endl;}if (sptr != nullptr) {// 非空分支}sptr = std::make_shared(7);if (sptr) {std::cout << "*sptr = " << *sptr << std::endl;}auto raw = sptr.get();if (raw) {std::cout << "raw 指针的值: " << *raw << std::endl;}
}

二、针对 unique_ptr 的空值判定方法

2.1 使用布尔上下文判断空值

最直观的做法是 if (uptr),它在布尔上下文中表达“非空”的意图,可读性高,也符合大多数你们的编码习惯。

C++ 智能指针是否为空如何判断?安全高效的空值判定方法(适用于 unique_ptr 与 shared_ptr)

在实现细节层面,布尔判断通常是内联且无开销的,不会额外产生动态分配或额外引用计数,因此在循环或条件分支中尤为高效。

std::unique_ptr uptr = std::make_unique(10);
if (uptr) {// 非空分支
}

2.2 与 nullptr 的显式比较

另一种常见写法是 if (uptr == nullptr)if (uptr != nullptr),适用于希望把空指针作为分支条件的一致性场景。

使用显式比较有助于与老代码风格对齐,避免对布尔上下文的理解分歧,但在可读性上通常不如直接 use 的布尔形式直观。

std::unique_ptr uptr;
if (uptr == nullptr) {// 处理空指针
}
uptr = std::make_unique(5);
if (uptr != nullptr) {// 非空分支
}

2.3 get() 的使用场景与风险

如果需要把原始指针传给只接受 T* 的函数,可以使用 uptr.get(),但要注意生命周期的一致性,避免在 raw 指针仍然在作用域内时销毁智能指针,导致悬空指针。

在判断阶段尽量避免通过 get() 做两次判断再进行后续操作,因为这会引发潜在的并发或生命周期错配问题,破坏 RAII 的安全性。

void takes_raw_ptr(const int* p) { /* 使用 p */ }void demo_with_get() {std::unique_ptr uptr = std::make_unique(8);if (uptr.get()) {takes_raw_ptr(uptr.get());}
}

三、针对 shared_ptr 的空值判定方法

3.1 使用布尔上下文判断空值

unique_ptr 一样,if (sptr) 是判断非空的最直接方式,具备相同的语义与性能优势。

实践中,使用布尔上下文可以让代码结构更紧凑,直接体现“对象是否引用了有效资源”的意图。

std::shared_ptr sptr;
if (sptr) {// 非空
}

3.2 与 nullptr 的显式比较

同样可以采用 if (sptr == nullptr)if (sptr != nullptr),用于统一风格或特定静态分析的需求。

显式比较在多分支逻辑中可能更易于理解,尤其是在与旧代码协同工作时。

std::shared_ptr sptr;
if (sptr == nullptr) {// 为空的分支
}

3.3 get() 的使用场景与风险

与 unique_ptr 类似,如果需要将原始指针传给需要 T* 的函数,可以通过 sptr.get() 获取;但请确保原始指针的生命周期与共享指针的控制块一致,避免悬空或多次释放带来的风险。

在大多数场景下,优先使用布尔上下文或 nullptr 比较,因为它们对生命周期的语义更清晰,且减少了错误风险。

void takes_raw_ptr(const int* p) { /* 使用 p */ }void demo_shared_get() {std::shared_ptr sptr = std::make_shared(42);if (sptr.get()) {takes_raw_ptr(sptr.get());}
}

广告

后端开发标签