c++ - 指向函数签名中 const 的智能指针

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

我想知道当将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>& ){}

最佳答案

为什么按值传递有效?

您的代码可以工作是因为 smart_ptr constructor overload (9) :

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

Constructs a shared_ptr which shares ownership of the object managed by r. If r manages no object, this manages no object too. The template overload doesn't participate in overload resolution if Y is not implicitly convertible to (until C++17)compatible with (since C++17) T*.

当该方法需要 shared_ptr<const Widget>& 时,为什么它无法编译? ?

如果您将签名更改为

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

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

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<const Widget>被构造然后传递给方法(就像上面的代码片段中明确显示的那样)。

当该方法需要 const shared_ptr<const Widget>& 时,为什么它会再次起作用? ?

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

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

在这种情况下,如果您传递 shared_ptr<Widget> ,仍有转换发生。但是,现在允许将转换产生的临时结果绑定(bind)到 const 引用。无论如何,该方法不允许修改它,因此允许传递临时值没有危险。

再举一个例子

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

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

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

将右值传递给需要非常量左值引用的函数没有多大意义。您将无法观察 foo 所做的更改关于 bar 返回的值。

传递智能指针@cpp核心准则

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

关于c++ - 指向函数签名中 const 的智能指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52591352/

相关文章:

c++ - 有没有更快的方法或优化我可以应用于我的即兴内存池?

c++ - 如何对 Windows 文本框中的数据执行三角函数

C++0x lambda,如何作为参数传递?

Swift:将 Any 转换为协议(protocol)对象数组

C# 无法从 SQL Server SELECT 转换计算列

c++ - QTextStream stdin readline 不暂停输入

java - 将 Java 嵌入到 C++ 应用程序中?

c++ - txt 文件的输入在第二次读取/传递时不匹配 (C++)

c++ - 如何使用 Clang 获取模板类型类成员的实际类型?

不能取消引用变量所以函数满足