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

C++指针引用丢失是否因作用域导致?C/C++有无引用计数?

问题

尝试让指针指向方法内创建的新MyClass类实例地址,但返回main函数后该指针引用丢失,请问这是否由作用域问题导致?能否解释具体原因?另外C/C++是否具备引用计数机制?

#include <iostream>

class MyClass {
public:
    int myNum;
    std::string myString;
    MyClass(int my_num, std::string my_string)
    {
        myNum = my_num;
        myString = my_string;
    }
};

void SwapRef(MyClass **p)
{    
    MyClass b(99, "test");
    *p = &b;
}

int main(int argc, char* argv[])
{
    MyClass a(1, "main");

    MyClass* aPtr = (MyClass*)0;
    aPtr = &a;

    std::cout << "myNum is: " << aPtr->myNum << " myString is: " << aPtr->myString << "\n";

    SwapRef(&aPtr);

    std::cout << "myNum is: " << aPtr->myNum << " myString is: " << aPtr->myString << "\n";

#ifdef _WIN32 || _WIN64
    system("pause");
#endif
}

程序输出:

myNum is: 1 myString is: main
myNum is: -858993460 myString is:
解答

一、指针引用丢失的核心原因:作用域导致的局部对象销毁

确实是作用域问题。你在SwapRef函数里创建的MyClass b是栈上的局部对象,它的作用域仅限于SwapRef函数内部。当函数执行完毕返回时,栈上的局部对象会被自动销毁,对应的内存空间会被操作系统回收或标记为可复用。

你把*p指向了这个局部对象的地址,等回到main函数时,这个地址已经不再属于有效的MyClass实例——内存里的内容已经被覆盖或清空,这时候通过aPtr访问就是未定义行为,所以会输出乱码(比如-858993460是Windows下未初始化内存的典型值)。

如果想让指针在main里仍然有效,有两种常见解决办法:

  • 在SwapRef里用new在堆上创建对象:*p = new MyClass(99, "test");,但要记得后续用delete释放内存,避免内存泄漏。
  • 把b定义为静态局部对象:static MyClass b(99, "test");,这样对象会存放在静态存储区,函数结束后不会被销毁,但静态对象的生命周期是整个程序运行期间,要注意复用问题。

二、C/C++的引用计数机制说明

  • C语言:标准C里没有内置的引用计数机制,需要手动实现(比如自己维护一个计数变量,在对象被引用时加1,释放时减1,计数为0时销毁对象)。
  • C++语言:标准C++本身没有全局内置的引用计数,但标准库提供了基于引用计数的智能指针:std::shared_ptr。它会自动跟踪对象被引用的次数,当最后一个shared_ptr销毁时,会自动释放指向的堆内存,避免内存泄漏。另外,std::weak_ptr可以配合shared_ptr使用,解决循环引用问题。

注意:std::unique_ptr是独占式智能指针,没有引用计数,它保证同一时间只有一个指针指向对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:46:19