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 也就分别各自是各自的,为什么会出现这种问题呢?还请牛人解释一下。

首先你第一段代码野指针了。
对于这段代码 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的,这次地址就不一样了。