将 unique_ptr 与需要指针指针的接口一起使用到抽象类

Posted

技术标签:

【中文标题】将 unique_ptr 与需要指针指针的接口一起使用到抽象类【英文标题】:Using unique_ptr with an interface requiring pointer-pointer, to an abstract class 【发布时间】:2021-09-27 16:29:45 【问题描述】:

我正在使用 RocksDB,它需要一个指向打开指针的指针:

rocksdb::DB* dbnullptr;
const rocksdb::Status status = rocksdb::DB::Open(options, path, &db);

正如预期的那样,我想使用unique_ptr。但是,不幸的是,如果我这样做:

std::unique_ptr<rocksdb::DB> db;
const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &(db.get()));

我明白了:

error: lvalue required as unary ‘&’ operand

如果我使用原始指针然后创建一个unique_ptr:

std::unique_ptr<rocksdb::DB> _db; // Class member
rocksdb::DB* db;
const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &db));
_db = std::make_unique<rocksdb::DB>(db);

我明白了:

 error: invalid new-expression of abstract class type ‘rocksdb::DB’
  return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); 

我该如何使用unique_ptr

【问题讨论】:

不应该是_db.reset(db);吗? 我认为reset() 只有当它当前持有一个有效值时,否则它是make_unique &amp;(db.get()) 翻译得到unique_ptr 所代表的地址,然后取地址的地址。不是你想要的。您收到的错误消息是因为返回的地址位于临时变量中,您无法获取临时地址。它们的存在时间还不够长,无法发挥作用。 @user4581301 这个页面隐含地暗示我可以在我希望的时候删除指针:rocksdb.org/docs/getting-started.html 好。消除了一个潜在的问题来源。 【参考方案1】:

使用原始指针接受来自Open() 的值是正确的解决方案,因为这是函数所期望的。

但是,您之后创建unique_ptr 的方式不正确。

改用这个:

std::unique_ptr<rocksdb::DB> _db; // Class member
...
rocksdb::DB* db;
const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &db);
_db = std::unique_ptr<rocksdb::DB>(db);

Online Demo

或者:

std::unique_ptr<rocksdb::DB> _db; // Class member
...
rocksdb::DB* db;
const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &db);
_db.reset(db);

Online Demo

std::make_unique() 创建指定类型的新对象,然后将原始指针包装在新的std::unique_ptr 中。

另一方面,unique_ptr::operator=unique_ptr::reset() 只是用新的原始指针更新现有的std::unique_ptr(销毁被替换的旧原始指针指向的对象)。

由于rocksdb::DB 是一种抽象类型,您不能直接创建它的实例,这就是您的std::make_unique() 调用无法编译的原因。但是,即使您可以直接创建 DB 对象,std::make_unique&lt;rocksdb::DB&gt;(db) 也会将 db 作为参数传递给 rocksdb::DB 构造函数,这在这种情况下无论如何都不是您想要的。您只希望_db 智能指针拥有db 原始指针的所有权。

【讨论】:

以上是关于将 unique_ptr 与需要指针指针的接口一起使用到抽象类的主要内容,如果未能解决你的问题,请参考以下文章

如何将 unique_ptr 与 std::copy 一起使用?

使用 std::unique_ptr.reset() 更改指针下的对象

智能指针之unique_ptr

C++ 智能指针 (unique_ptr)

再探 智能指针

shared_ptr 和 unique_ptr