【问题标题】:Create aliases to boost::shared_ptr via reference通过引用为 boost::shared_ptr 创建别名
【发布时间】:2016-09-26 11:50:11
【问题描述】:

我有一小段代码需要优化。线程“A”为堆对象创建了一个 boost shared_ptr。线程“A”将 shared_ptr 写入线程安全队列。线程“B”读取 shared_ptr,使用它,然后销毁它。

密集的分析/测试证明,将 shared_ptr 复制进/出队列并调整引用计数是昂贵的。因此,我想通过引用将共享 ptr 传递给队列。我还想使用 std::move 将 shared_ptr 移动到队列中,而不是构造一个新的 shared_ptr,(我知道这会使传递给队列的 shared_ptr 参数无效)。

在我加入一些多态性之前,所描述的一切都很好。我不能通过 ref 将 shared_ptr 传递给派生的 obj 到期望将 shared_ptr 传递给基类的函数。我把它归结为一个非常小的片段,它暴露了让我困惑的行为。

#include <boost/shared_ptr.hpp>

class Base
{
};

class Derived : public Base
{
};

int main()
{
  boost::shared_ptr<Derived> pDerived(new Derived());  // simple creation
  boost::shared_ptr<Derived> &alias1 = pDerived;       // works fine
  const boost::shared_ptr<Base> &alias2 = pDerived;    // also works fine
  boost::shared_ptr<Base> &alias3 = pDerived;          // compilation error

  //native pointers
  Derived *alias4 = pDerived.get();     //works
  const Base *alias5 = pDerived.get();  //works
  Base *alias6 = pDerived.get();        //works

  //native references
  Derived &alias7 = *pDerived;          // works
  const Base &alias8 = *pDerived;       // works
  Base &alias9 = *pDerived;             // works
}

我不明白为什么分配给 alias2 是完全正常的,但是分配给 alias3 会产生编译器错误。有人可以解释一下吗?我需要类似 alias3 示例的功能,但无法使其工作。

【问题讨论】:

  • std::shared_ptr&lt;Base&gt;&amp; alias3 = static_cast&lt;std::shared_ptr&lt;Base&gt;&gt;( pDerived );
  • 你也可以尝试使用 boosts static_cast: alias3 = boost::static_pointer_cast&lt;Base&gt;(pDerived);
  • 就像 Eissa N. 建议的那样,强制转换会导致编译错误:invalid initialization of non-const reference of type âboost::shared_ptr&lt;Base&gt;&amp;â from an rvalue of type âboost::shared_ptr&lt;Base&gt;â boost::shared_ptr&lt;Base&gt; &amp;alias3 = boost::static_pointer_cast&lt;Base&gt;(pDerived); 即使这确实有效,临时 rval 对象的创建正是我出于效率原因试图避免的.

标签: c++ multithreading boost reference shared-ptr


【解决方案1】:

此问题与 boost 或智能指针无关。 POD 类型也可能发生这种情况,如下面的简单示例所示:

int main() {
    int x = 0;
    const double &y = x; //fine
    double &z = x; //error!
    return 0;
}

原因是临时值(右值)可以绑定到const&amp;,但不能绑定到&amp;。在double &amp;z = x 中发生的是xz 是不相关的类型,而x 需要转换为double 并创建一个临时变量,该变量不能绑定到&amp;

【讨论】:

  • Eissa N. -- 我怀疑你是完全正确的;谢谢。但是,请参阅示例中添加的附加行。本机指针和引用似乎不需要像您建议的那样创建临时 rval (可能是因为编译器本机理解连接结构中的成员偏移量)。也许这只是 shared_ptr 容器/模板不是其原生对应物的干净替代品的另一种方式。
  • @njensen 如果您将原始指针与智能指针进行比较,您应该检查 Derived* pDerived = new Derived; Base* &amp;alias = pDerived; 再次失败。
  • 如果可以的话,我会投票给你;显然我太新了,无法计算我的选票。我同意你的最后一个例子准确地暴露了这个问题。
  • @njensen 另外,另一方面:BaseDerived 是相关类型(通过继承),因此在 Base &amp;alias9 = *pDerived; 中绑定它们可以正常工作。但是,Base*Derived* 仍然是不相关的类型,因此使用 &amp; 绑定它们会失败。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 2013-04-16
  • 1970-01-01
  • 2011-04-19
  • 2021-10-10
  • 1970-01-01
相关资源
最近更新 更多