文章目录一、用指针还是引用1. 语义上的区别最重要2. 空值检查Nullability3. 重新赋值Reassignment4. 初始化时机 总结与最佳实践一、用指针还是引用在现代 C 中引用和指针*在底层实现上几乎是一样的通常都是一个内存地址但在语义表达和使用规范上有显著的区别。针对您的场景在类中持有外部传入的依赖对象如DbService强烈推荐使用引用DbService。以下是它们的核心区别1. 语义上的区别最重要引用代表**“强绑定”和“必须存在”**。它向阅读代码的人明确宣告“这个对象是我正常工作所必需的它一定不为空并且在我的整个生命周期内都不会改变指向。”指针*代表**“可选”或“可变”**。它暗示“这个对象可能为空nullptr或者在运行过程中可能会指向另一个对象。”2. 空值检查Nullability引用在 C 标准中引用不能为空尽管通过一些黑客手段可以制造空引用但这属于未定义行为 UB。因此您在使用db_service_时不需要每次都写if (db_service_ ! nullptr)代码更简洁。指针理论上可以为空。如果您用指针严谨的代码在每次使用前都需要检查它是否为空否则会有崩溃的风险。3. 重新赋值Reassignment引用一旦在构造函数中初始化就永远不能再指向别的对象。这保证了依赖关系的绝对稳定。指针可以随时被重新赋值例如db_service_ another_service;。如果您的业务逻辑不需要在运行时更换数据库服务使用指针反而留下了误操作的风险。4. 初始化时机引用必须在构造函数的初始化列表中进行初始化。这迫使您在创建对象时就提供依赖避免了“两阶段初始化”的麻烦。指针可以在构造函数内部赋值或者提供一个setDbService(DbService* db)的方法稍后赋值。 总结与最佳实践在现代 C 的类设计中关于如何持有外部依赖有一个不成文的黄金法则如果依赖是必须的且不需要更换使用引用DbService您的UserLoginRecord必须依赖DbService所以用引用最完美。如果依赖是可选的可能为空使用指针DbService*例如一个可选的日志记录器如果没有配置就不记录。如果依赖是必须的且需要转移所有权使用智能指针std::unique_ptrDbService您的main函数中用unique_ptr管理对象是正确的因为main拥有这些对象的所有权。但作为被注入的依赖其他类只“使用”它不“拥有”它所以用引用。一句话总结用引用是在表达**“契约”我保证它一定在用指针*是在表达“可能性”**它可能存在也可能不存在。您的场景属于强契约所以DbService是最优雅的选择。