You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何非const的std::shared_ptr引用无法实现多态?

为什么以多态方式使用std::shared_ptr时,std::shared_ptr&无法正常工作,但const std::shared_ptr&可以?

我在尝试用多态方式使用std::shared_ptr时遇到了一个问题:函数参数为const std::shared_ptr<A>&时可以正常运行,但参数为std::shared_ptr<A>&时会编译报错。以下是测试代码:

#include <iostream>
#include <memory>

class A {
public:
    virtual void foo() { std::cout << "A" << std::endl; }
};

class B : public A {
public:
    void foo() override { std::cout << "B" << std::endl; }
};

void working(const std::shared_ptr<A>& ptr) {
    ptr->foo();
}

void not_working(std::shared_ptr<A>& ptr) {
    ptr->foo();
}

int main() {
    auto ptr = std::make_shared<B>();
    working(ptr);

    not_working(ptr); // <-- 编译错误

    return 0;
}

编译后得到的错误信息如下:

main.cpp: In function ‘int main()’:
main.cpp:24:16: error: cannot bind non-const lvalue reference of type ‘std::shared_ptr<A>&’ to an rvalue of type ‘std::shared_ptr<A>’
   24 |     not_working(ptr);
      |                ^~~
In file included from /usr/include/c++/11/memory:77,
                 from main.cpp:2:
/usr/include/c++/11/bits/shared_ptr.h:296:9: note:   after user-defined conversion: ‘std::shared_ptr<_Tp>::shared_ptr(const std::shared_ptr<_Yp>&) [with _Yp = B; <template-parameter-2-2> = void; _Tp = A]’
  296 |         shared_ptr(const shared_ptr<_Yp>& __r) noexcept
      |         ^~~~~~~~~~
main.cpp:18:37: note:   initializing argument 1 of ‘void not_working(std::shared_ptr<A>&)’
   18 | void not_working(std::shared_ptr<A>& ptr) {
      |                 ~~~~~~~~~~~~~~~~~~~~^~~
make: *** [&lt;builtin&gt;: main] Error 1

原因解析

核心问题在于C++的引用绑定规则:

  • 当你将std::shared_ptr<B>传递给期望std::shared_ptr<A>&的函数时,编译器会触发std::shared_ptr的转换构造函数,创建一个临时的std::shared_ptr<A>对象(因为B是A的子类,shared_ptr支持这种向上转型)。
  • 这个临时对象属于右值,C++明确规定:非const的左值引用(&)无法绑定到右值,但const左值引用(const &)可以绑定到右值,并且会延长临时对象的生命周期。

具体到代码:

  1. 调用working(ptr)时,参数是const std::shared_ptr<A>&,临时生成的std::shared_ptr<A>可以合法绑定到这个const引用上,因此编译通过,且多态调用正常(ptr->foo()会调用B的foo)。
  2. 调用not_working(ptr)时,参数是std::shared_ptr<A>&,临时的std::shared_ptr<A>是右值,无法绑定到非const左值引用,因此触发编译错误。

解决方法

如果确实需要在not_working中修改传入的shared_ptr(比如重置它),可以提前将std::shared_ptr<B>显式转换为std::shared_ptr<A>再传递:

std::shared_ptr<A> a_ptr = ptr;
not_working(a_ptr);

如果不需要修改传入的shared_ptr,使用const std::shared_ptr<A>&是最优选择——它既支持多态场景的隐式转换,又避免了不必要的shared_ptr拷贝。


内容的提问来源于stack exchange,提问作者antibus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 02:27:43