如何 push_back unique_ptr 参数到共享 ptr 的向量上

Posted

技术标签:

【中文标题】如何 push_back unique_ptr 参数到共享 ptr 的向量上【英文标题】:How push_back unique_ptr parameter onto vector of shared ptrs 【发布时间】:2015-01-07 15:15:48 【问题描述】:

我很难将 unique_ptr 从我的方法参数推回共享指针向量。

IFCCB.h:

private:
vector<shared_ptr<IFC>>  m_shpVectorIFC;
public:
void addElementVectorIFC(unique_ptr<IFC> rupIFC);

IFCCB.cpp:

void IFCCB::addElementVectorIFC(unique_ptr<IFC> rupIFC)

    m_shpVectorIFC.push_back(std::unique_ptr<IFC>(new IFContent(rupIFC)));

我收到了错误:

C2664: 'IFC::IFC(const IFC &)' : 无法将参数 1 从 'std::unique_ptr>' 到 'IFO *'

在这种情况下,IFO 是 IFC 的层级父级。我不知道它为什么会这样看。

我查看了vector info 和shared_ptr info,以及using unique_ptr with standard library containers。

有什么想法吗?我不习惯使用 shared_ptrs 和 unique_ptrs。

【问题讨论】:

很难说,但在我看来,您的错误是 IFContent 构造函数不接受 unique_ptr&lt;IFCt&gt; IFC 构造函数有一个 IFO* 参数。但是 IFC 的默认构造函数不应该接受 IFC 吗? (顺便说一句,这是一个错字...IFCt 现在正在更改为上面的 IFC)。 你真的想从rupIFC 参数创建一个新对象,还是仅仅因为你不能让它工作?您是否只想将rupIFC 推送到容器中? 这是我想到的第一个方法。我不认为我可以将我的唯一指针 push_back 到 shared_ptrs 的向量上。它们需要不同……unique_ptr 和 shared_ptrs 的 vec。 但是,如果您认为它行不通,为什么还要尝试使用新的 unique_ptr 做完全相同的事情?! 【参考方案1】:

问题在于push_back 采用容器的value_type,即shared_ptr&lt;IFC&gt;,但您传递给它的是unique_ptr&lt;IFC&gt;,并且从unique_ptrshared_ptr 的转换使用explicit 构造函数和只能从unique_ptr 右值完成,因此参数不能隐式转换为shared_ptr

要使其正常工作,您需要使用std::moveunique_ptr 转换为右值,然后显式转换为shared_ptr

unique_ptr<IFC> p;
// ...
m_shpVectorIFC.push_back(std::shared_ptr<IFC>(std::move(p)));

或者改用emplace_back,因为该函数可以使用explicit构造函数来构造新的容器元素:

m_shpVectorIFC.emplace_back(std::move(p)));

我不相信您创建新 unique_ptr 的代码是正确的(为什么您不能使用上面显示的任一解决方案将 rupIFC 插入容器中?)但如果这确实是您想要的这样做,您得到的错误是因为您试图将unique_ptr&lt;IFC&gt; 传递给IFContent 构造函数,该构造函数采用IFO* 而不是unique_ptr&lt;IFC&gt;。要进行编译,您需要从rupIFC 中获取原始指针:

std::unique_ptr<IFC>(new IFContent(rupIFC.get()))

但是这可能是不安全的,因为当rupIFC 被销毁时,您传递给IFContent 构造函数的指针将在函数末尾被删除,所以也许您打算释放它:

std::unique_ptr<IFC>(new IFContent(rupIFC.release()))

注意正如 dlf 的回答所说,如果您只想立即将其转换为 shared_ptr,那么创建 unique_ptr 是没有意义的,所以您可以简单地这样做:

m_shpVectorIFC.emplace_back(std::make_shared<IFContent>(rupIFC.release()));

【讨论】:

创建一个新副本应该没问题,因为当我执行 get/pop 时,我也在创建一个副本。【参考方案2】:

根据您的附录,您将需要使用 unique_ptr::get()IFContent 构造函数提供所需的原始指针。根据它对该指针的作用,您实际上可能需要使用release 来防止双重删除。此外,无需创建中间 unique_ptr,因为它只是要直接转换为 shared_ptr

void IFCCB::addElementVectorIFC(unique_ptr<IFC> rupIFC)

    m_shpVectorIFC.push_back(std::shared_ptr<IFC>(new IFContent(rupIFC.get())));

【讨论】:

我没有 rupIFC.get() 的吸气剂。我应该可以在这里使用默认构造函数,m_shpVectorIFC.push_back(std::shared_ptr(new IFContent(rupIFC))),不应该吗? rupIFC 是一个unique_ptr,它定义了get() 以提供一个指向底层对象的原始指针(我认为您表示IFContent 的构造函数需要一个原始指针?)。 只要确保所有权明确定义——如果IFContent 持有该指针并稍后尝试删除它,那么当原始unique_ptr 执行相同操作时,您将遇到麻烦。 unique_ptr 可转换为 shared_ptr,因此您可以执行此操作 能够将所有权从一个智能指针转移到另一个智能指针有什么令人惊讶的?转换是完全安全的,具有释放unique_ptr 拥有的对象并将所有权转移给shared_ptr 的效果。

以上是关于如何 push_back unique_ptr 参数到共享 ptr 的向量上的主要内容,如果未能解决你的问题,请参考以下文章

我可以制作一个 unique_ptr 不获取其指向对象的所有权吗?

如何在向量内部引用一对?

push_back与构造函数

如何将 std::unique_ptr 初始化为引用

如何使用 SWIG 处理 unique_ptr

如何初始化一个unique_ptr