如何在编译期阻止类构造函数接收NULL指针?
编译期阻止类接收NULL指针的方案
针对你提出的需求,以下几种方案可以在编译期强制类A的构造函数接收非空指针,同时避免每个成员函数都做空指针检查:
方案1:改用引用替代指针
C++中的引用编译期就必须绑定到有效对象,无法为null,是最直接的解决方案。只需修改构造函数参数类型,同时初始化内部指针:
class B { // 类B的API }; class A { private: B* ptrB_; // 或直接使用B& refB_; public: // 构造函数接收B的引用,确保传入非空对象 explicit A(B& b) : ptrB_(&b) {} void Func1() { // 无需空指针检查,ptrB_必然指向有效对象 // ... 原有逻辑 } }; int main() { B tempB; A tempA(tempB); // 正确:传入有效对象的引用 // 以下代码会编译报错,无法传入空值 // A invalidA(nullptr); // B* nullPtr = nullptr; // A invalidA(*nullPtr); }
这种方案无需额外依赖,编译期直接阻断空值传入,代码最简洁。
方案2:使用std::not_null(C++17及以上)
如果必须保留指针类型,可以用C++17标准库的std::not_null(或早期GSL库的gsl::not_null)包装指针,它会在编译期检查常量空值,运行期兜底检查变量空值:
#include <memory> // C++17引入std::not_null class B { // 类B的API }; class A { private: std::not_null<B*> ptrB_; public: explicit A(std::not_null<B*> ptrB) : ptrB_(ptrB) {} void Func1() { // 无需空指针检查,ptrB_保证非空 // ... 原有逻辑 } }; int main() { B tempB; A tempA(&tempB); // 正确:传入有效指针 // 以下代码编译期报错 // A invalidA(nullptr); }
如果传入运行期生成的空指针(如某个函数返回null),std::not_null会触发断言或抛出异常,避免后续逻辑出错。
方案3:禁用nullptr构造重载(兼容旧标准)
如果使用C++17之前的版本,可以通过删除std::nullptr_t参数的构造函数重载,在编译期阻止显式传入nullptr,同时保留运行期的断言兜底:
#include <cassert> class B { // 类B的API }; class A { private: B* ptrB_; public: explicit A(B* ptrB) : ptrB_(ptrB) { // 运行期兜底检查,防止传入运行期生成的空指针 assert(ptrB_ != nullptr && "ptrB cannot be null"); } // 删除接收nullptr的构造函数,编译期阻止空值传入 A(std::nullptr_t) = delete; }; int main() { B tempB; A tempA(&tempB); // 正确 // 以下代码编译报错 // A invalidA(nullptr); }
这种方案兼容C++11及以上版本,既能在编译期阻止显式nullptr,又能通过断言捕获运行期意外的空指针。
内容的提问来源于stack exchange,提问作者Shanti Schul
相关产品推荐
相关产品推荐

