【问题标题】:smart pointer to const in function's signature函数签名中指向 const 的智能指针
【发布时间】:2019-03-06 13:51:43
【问题描述】:

我想知道在将 shared_ptr 作为参数传递给采用 shared_ptr 的函数时,隐式转换是否涉及一些隐藏成本(例如构建额外副本)。

void f(std::shared_ptr<const Widget> ){}

int main(){
   std::shared_ptr<Widget> p; 
   f(p);
   return 0;
}

我假设在这两种情况下我都要为引用计数的递增和递减付费。

此外,我想知道如果我使用以下签名定义函数f(),为什么代码无法编译:

void f(shared_ptr<const Widget>& ){}

更让我惊讶的是,它确实做到了:

void f(const shared_ptr<const Widget>& ){}

【问题讨论】:

  • 谢谢,我编辑了这个问题。
  • 1. T 是什么? 2. 提供一个可编译的例子或至少一个错误信息。
  • 如果f 只关心在其持续时间内使用Widget,请传递const Widget *(或const Widget &amp;,如果你知道它是非空的)。只有当f 希望参与拥有Widget(即它将指针存储在某处)时,您才应该传递shared_ptr
  • @Caleth 假设我无法更改 f 的签名。无论如何,我完全同意你的建议。

标签: c++ c++11 casting const-correctness


【解决方案1】:

为什么按值传递有效?

由于smart_ptr constructor overload (9),您的代码有效:

template< class Y >
shared_ptr( const shared_ptr<Y>& r ) noexcept;

构造一个shared_ptr,它共享被管理对象的所有权 由 r.如果 r 不管理任何对象,this 也不管理任何对象。这 如果 Y 是,则模板重载不参与重载决议 不能隐式转换为(C++17 前)兼容(因为 C++17) T*。

为什么当方法需要 shared_ptr&lt;const Widget&gt;&amp; 时它无法编译?

如果您将签名更改为

void f(shared_ptr<const Widget>& ){}

您不能再一步完成转换并传递给方法,因为临时(由转换产生的)不能绑定到非常量引用。但是,您仍然可以分两步完成:

int main(){
    std::shared_ptr<Widget> p; 
    std::shared_ptr<const Widget> p2{p};
    // f(p);  // error: cannot bind non-const reference to temporary
    f(p2);    // OK
    return 0;
}

是否有一些开销?

关于开销:是的,有一个 smart_ptr&lt;const Widget&gt; 正在构造,然后传递给方法(就像上面的 sn-p 中明确显示的那样)。

为什么当方法需要 const shared_ptr&lt;const Widget&gt;&amp; 时它再次起作用?

关于您的编辑,如果您将签名更改为此,为什么它会再次起作用:

void f(const shared_ptr<const Widget>& ){}

在这种情况下,如果您通过shared_ptr&lt;Widget&gt;,仍然会发生转换。但是,现在允许转换产生的临时结果绑定到 const 引用。无论如何,该方法不允许修改它,因此允许通过临时没有危险。

只是另一个例子

请注意,不绑定到非常量引用的临时变量是 C++ 帮助您避免愚蠢错误的罕见情况。考虑一下:

void foo(int& x) { x += 2; }
int bar() { return 3; }

int main() { foo(bar()); }   // error !

将 r 值传递给需要非 const 左值引用的函数没有多大意义。您无法观察到foobar 返回的值所做的更改。

通过智能指针@cpp 核心指南

关于将智能指针传递给函数,请注意cpp coreguidelines 有一些项目。底线是:如果方法不参与引用计数(可能是最常见的情况),则不要传递智能指针,而是传递原始指针。

【讨论】:

  • 可能值得一提的是,将智能指针传递给函数被认为是一种气味,除非该函数正在获取指针的所有权。这个想法是您应该只将实时(和原始)指针传递给只需要使用该对象的方法。
  • @Mgetz 是的,值得一提 ;-) 感谢您这样做。
  • 您好 user463035818,我用另一个案例编辑了我的问题。我可以将它写在一个单独的问题中,但我认为最好将这些东西放在一起,因为它们密切相关。我希望您或一些仁慈的人有时间编辑您讨论“const & const”案例的答案。谢谢
  • @jimifiki 对不起,忽略我的评论(已删除)。我写得太快了;)。我的回答实际上已经解释了为什么您添加的内容确实有效。将编辑问题以解释更多...
猜你喜欢
  • 2020-12-04
  • 2016-10-09
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多