XZshijian 2022-11-23 10:04 采纳率: 100%
浏览 4
已结题

c++智能指针使用问题

问题遇到的现象和发生背景

有一个简单的问题想要问一下各位。

用代码块功能插入代码,请勿粘贴截图
    WeldRecipeSC* ActiveRecipeSC1 = WeldRecipeSC::GetWeldRecipeSC().get();
    WeldRecipeSC* ActiveRecipeSC2 = WeldRecipeSC::GetWeldRecipeSC().get();
    cout << ActiveRecipeSC1 << endl;
    cout << ActiveRecipeSC2 << endl;
    ActiveRecipeSC1 ->m_RecipeID = 1;
    ActiveRecipeSC2 ->m_RecipeID = 2;
    cout << ActiveRecipeSC1->m_RecipeID << endl;
    cout << ActiveRecipeSC2->m_RecipeID<< endl;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    std::shared_ptr<WeldRecipeSC> RecipeSC3 = WeldRecipeSC::GetWeldRecipeSC();
    std::shared_ptr<WeldRecipeSC> RecipeSC4 = WeldRecipeSC::GetWeldRecipeSC();
    cout << RecipeSC3 << endl;
    cout << RecipeSC4 << endl;
    cout << RecipeSC3.get() << endl;
    cout << RecipeSC4.get() << endl;
    RecipeSC3.get()->m_RecipeID = 1;
    RecipeSC4.get()->m_RecipeID = 2;
    cout << RecipeSC3.get()->m_RecipeID << endl;
    cout << RecipeSC4.get()->m_RecipeID << endl;
/////////////////////////////////////////////////////////GetWeldRecipeSC()//////////////////////////////////////////////////////////////
std::shared_ptr<WeldRecipeSC> WeldRecipeSC::GetWeldRecipeSC()
{
    std::shared_ptr<WeldRecipeSC> ptrWeldRecipeSC = nullptr;
    ptrWeldRecipeSC = std::make_shared<A>();//A是WeldRecipeSC的子类
    return ptrWeldRecipeSC;
}
运行结果及报错内容

第一段代码打印出来的地址是相同的,当改变了ActiveRecipeSC2 ->m_RecipeID,那么ActiveRecipeSC1 ->m_RecipeID也就会被改变,而第二段代码RecipeSC3 和RecipeSC4 地址不同, RecipeSC3.get()和RecipeSC4.get()地址也不同,所以m_RecipeID 也就分别各自是各自的,为什么会出现这种问题呢?还请牛人解释一下。

  • 写回答

2条回答 默认 最新

  • HelixRay 2022-11-23 12:09
    关注

    首先你第一段代码野指针了。
    对于这段代码 WeldRecipeSC* ActiveRecipeSC1=WeldRecipeSC::GetWeldRecipeSC().get();
    首先 WeldRecipeSC::GetWeldRecipeSC()返回了一个shared_ptr的临时对象,这个临时对象的生命周期在调用get()获取裸指针后就结束了,所以在拿到WeldRecipeSC*的裸指针后 ,引用计数归零,你拿到的裸指针被delete掉。所以你拿到的两个指针都是野指针。第二段代码才是正确的用法。
    我用代码模拟了一下你这个场景

    class Point{
    public:
        Point (int x,int y):_x(x),_y(y){}
        ~Point(){cout<<"~Point()"<<endl;}
    
        int _x,_y;
    };
    
    shared_ptr<Point> getP(){
        shared_ptr<Point> p=nullptr;
        p=make_shared<Point>(1,2);
        return p;
    }
    
    int main(){
        auto p=getP().get();
        cout<<p<<endl;
        auto p2=getP().get();
        cout<<p2<<endl;
        return 0;
    }
    /*
    输出:
    ~Point()
    0x5647a83f5ec0
    ~Point()
    0x5647a83f5ec0
    */
    

    可以看到,在打印Point地址前Point的生命周期就已经结束了。
    至于为什么两个地址一样,可能和new/delete的底层实现有关,这个我没研究过,我猜是因为直接复用了上一次delete的堆空间。
    这个可以用代码复现一下

    int main(){
        auto p1=new Point(1,2);
        cout<<"p1: "<<p1<<endl;
        delete p1;
        auto p2 =new Point(3,2);
        cout<<"p2: "<<p2<<endl;
        delete p2;
    }
    /*
    输出
    0x55749283deb0
    0x55749283deb0
    两个地址一样
    */
    

    更改代码

    int main(){
        auto p1=new int(1);
        cout<<"p1: "<<p1<<endl;
        delete p1;
        auto tmp=new float();
        cout<<"tmp: "<<tmp<<endl;
        auto p2 =new int(1);
        cout<<"p2: "<<p2<<endl;
        delete p2;
        delete tmp;//把tmp放到new之后再delete
        return 0;
    }
    /*
    输出:
    p1: 0x55c295f07eb0
    ~Point()
    tmp: 0x55c295f07eb0
    p2: 0x55c295f082e0
    ~Point()
    */
    

    在p1 delete之后紧接着new tmp,tmp和p1的起始地址是一样的
    而p2在delete之前new的,这次地址就不一样了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 12月2日
  • 已采纳回答 11月24日
  • 修改了问题 11月23日
  • 创建了问题 11月23日

悬赏问题

  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么