如何将std::unique_ptr用于需传入二级指针的RocksDB抽象类接口
用std::unique_ptr管理RocksDB实例的正确方案
错误根因分析
- 第一种写法报错原因:
std::unique_ptr::get()方法返回的是持有的指针的临时右值副本,C++语法不允许对右值取地址,因此触发lvalue required as unary ‘&’ operand错误。 - 第二种写法报错原因:
rocksdb::DB是抽象类,std::make_unique的核心逻辑是新建对应类型的实例,会执行new rocksdb::DB(...)操作,抽象类无法被实例化,因此编译失败。std::make_unique仅适用于创建新对象,不能用来接管已经存在的原始指针。
正确实现方式
核心思路是先用原始指针接收RocksDB Open接口返回的实例,确认打开成功后,直接将原始指针交给std::unique_ptr管理即可。
普通局部变量场景
rocksdb::DB* raw_db = nullptr; const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &raw_db); if (!status.ok()) { // 自定义打开失败的处理逻辑,如打印日志、返回错误码等 // 打开失败时raw_db仍为nullptr,无需手动释放 } // 打开成功,用unique_ptr接管原始指针 std::unique_ptr<rocksdb::DB> db(raw_db);
类成员变量场景
如果unique_ptr是预先声明的类成员,使用reset方法传入原始指针即可:
// 类内成员声明 std::unique_ptr<rocksdb::DB> _db; // 成员初始化逻辑 rocksdb::DB* raw_db = nullptr; const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &raw_db); if (status.ok()) { _db.reset(raw_db); } else { // 自定义错误处理逻辑 }
注意事项
rocksdb::DB的析构函数为虚函数,使用std::unique_ptr<rocksdb::DB>的默认删除器即可正确完成资源释放,不需要额外自定义删除器。- 必须先校验Open接口的返回状态,只有状态正常时再将原始指针交给unique_ptr管理,避免接管空指针或非法指针。
内容的提问来源于stack exchange,提问作者user997112
相关产品推荐
相关产品推荐

