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

reset后std::shared_ptr仍可调用成员函数?原因及裸指针情况分析

std::shared_ptr reset()后调用成员函数的疑问

测试代码

// C++ program to demonstrate shared_ptr
#include <iostream>
#include <memory>

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

int main()
{
    std::shared_ptr<A> p1(new A);
    std::cout << p1.get() << std::endl;
    p1->show();
    std::shared_ptr<A> p2(p1);
    p2->show();
    std::cout << p1.get() << std::endl;
    std::cout << p2.get() << std::endl;

    // Returns the number of shared_ptr objects
    // referring to the same managed object.
    std::cout << p1.use_count() << std::endl;
    std::cout << p2.use_count() << std::endl;

    // Relinquishes ownership of p1 on the object
    // and pointer becomes NULL
    p1.reset();
    std::cout << p1.get() << std::endl;
    std::cout << p2.use_count() << std::endl;
    std::cout << p2.get() << std::endl;
    p1->show();
    p2->show();
    std::cout << p1.get() << std::endl;
    std::cout << p2.use_count() << std::endl;
    std::cout << p2.get() << std::endl;

    return 0;
}

程序输出

0x24dc5ef1790
A::show()
A::show()
0x24dc5ef1790
0x24dc5ef1790
2
2
0
1
0x24dc5ef1790
A::show() 
A::show()
0
1
0x24dc5ef1790

问题解答

为什么p1.reset()后调用p1->show()仍能输出结果?

首先要明确:这属于C++标准定义的未定义行为,并非语言的设计特性,只是当前环境下侥幸运行成功,原因有两点:

  • show()是非虚成员函数:这类函数的调用地址在编译阶段就已确定,不需要通过对象实例的虚表动态查找,编译后会直接生成调用A::show()的指令;
  • show()没有访问类的成员变量,也没有使用隐式的this指针:即使p1是空指针,调用函数时传递的this指针是nullptr,但函数内部没有对this指针做任何解引用操作,所以不会触发非法内存访问,因此能正常输出字符串。

裸指针是否存在相同情况?

是的,裸指针也会出现这种现象。比如执行以下代码:

A* ptr = nullptr;
ptr->show();

同样可能输出A::show(),但这同样是未定义行为——C++标准不保证这种情况一定能正常运行,在不同编译器、不同运行环境下,可能直接触发程序崩溃,或者出现其他不可预料的结果。

重要提醒:永远不要依赖这种未定义行为编写代码,空指针(无论智能指针还是裸指针)调用成员函数本身就是错误的写法,必须在调用前确保指针指向有效的对象实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:15:31