一次測試測試(C++11)智能指針引用的崩潰結論

項目中用到了智能指針,可是要在智能指針指向的類中獲取此類的shared_ptr指針傳給其引用的類,結果出現了問題,函數

測試代碼以下: (包括錯誤解釋)測試

 

  1 //測試 shared_ptr weak_ptr  map<string,shared_ptr>
  2 #include <stdio.h> //pinrtf ...
  3 #include <string>  //string ...
  4 #include <map>
  5 #include <memory>  //shared_ptr ...
  6 
  7 class C;
  8 
  9 class A {
 10 public:
 11     A() { printf("A()\n"); }
 12     ~A() { printf("~A()\n"); }
 13 
 14     std::string a;
 15     std::weak_ptr<C> with;
 16     virtual std::string geta() = 0;
 17 };
 18 
 19 class A1:public A {
 20 public:
 21     A1(std::string aa) { a = aa; printf("A1(%s)\n",aa.c_str()); };
 22     ~A1() { printf("~A1(%s)\n", a.c_str()); }
 23 
 24     std::string geta() { std::string b = "A1 " + a; return b; }
 25 };
 26 
 27 class A2:public A {
 28 public:
 29     A2(std::string aa) { a = aa; printf("A2(%s)\n", aa.c_str()); };
 30     ~A2() { printf("~A2()\n"); printf("~A2(%s)\n", a.c_str()); }
 31 
 32     std::string geta() { std::string b = "A2 " + a; return b; }
 33 };
 34 
 35 typedef std::shared_ptr<A> shrA;
 36 typedef std::shared_ptr<A1> shrA1;
 37 typedef std::shared_ptr<A2> shrA2;
 38 
 39 template<class _ty>
 40 class AA {
 41 public:
 42     AA() { printf("AA()\n"); }
 43     ~AA() { printf("~AA()\n"); }
 44 
 45     typedef std::map<std::string, _ty> Atype;
 46     Atype list;
 47 };
 48 
 49 
 50 class C
 51 {
 52 public:
 53     C() { printf("C()\n"); }
 54     ~C() { printf("~C()\n"); }//在這個析構函數中下斷點會發現進入兩次的,兩次析構  55     shrA h1, h2;
 56     std::weak_ptr<A> a;
 57 
 58     void add(shrA h) { 
 59         if (h1 == nullptr) {
 60             h1 = h;
 61             //std::shared_ptr<C> p = (std::shared_ptr<C>)this;//此法雖然不會釋放內存了,可是引用計數不對(此處是weak_ptr,可是shared_ptr計數也不對的)
 62             h->with = std::shared_ptr<C>(this); //這樣寫會在賦值的過程當中產生一次建立臨時對象(包括構造和析構,會釋放掉this的內存)
 63                                                 //由於以這種方式寫的話,在這裏是用this直接生成了shared_ptr,因此引用計數會變成1,致使在這次析構時釋放掉內存
 64                                                 //而致使外面的引用指針指向了被釋放掉的內存,,,so,崩潰~~
 65         }
 66         else if(h2 == nullptr) {
 67             h2 = h;
 68             h->with = std::shared_ptr<C>(this);//同上
 69         }
 70         printf("C::add %s\n",h->geta().c_str());
 71     }
 72 };
 73 typedef std::shared_ptr<C> shrC;
 74 
 75 class CC
 76 {
 77 public :
 78     CC() { printf("CC()\n"); }
 79     ~CC() { printf("~CC()\n"); }
 80 
 81     typedef std::map<std::string, std::shared_ptr<C>> Ctype;
 82     Ctype list;
 83 };
 84 
 85 int main() {
 86     {
 87         AA<shrA1> aa1;
 88         AA<shrA2> aa2;
 89 
 90         CC cc;
 91 
 92         shrA1 a1 = shrA1(new A1(""));
 93         auto b = aa1.list.emplace(std::make_pair("a1", a1));
 94 
 95         shrA1 a11 = shrA1(new A1("啊啊"));
 96         b = aa1.list.emplace(std::make_pair("a1", a11));//key 重複,放置失敗  (b.seond==false)
 97 
 98         shrA2 a2(new A2("份飯"));
 99         auto b2 = aa2.list.emplace(std::make_pair("a2", a2));
100 
101         printf("\n-----  --------\n");
102         for (auto p : aa1.list)
103             printf("%s\n", p.second->geta().data());
104         printf("\n-----  --------\n");
105         shrC c(new C());
106         cc.list.emplace("c1", c);
107         //c->add(a11);  c->add  a1/a11/a2  都會致使崩潰
108         c->add(a2);
109     }
110     return 0;
111 }

 

結論:this

在賦值過程當中,用形如spa

std::shared_ptr<C>(this)

的方式取得本指針的shared_ptr指針,會產生新的shared_ptr指針,,,而不是你想要的那個指針(類外定義的那個指針),指針

雖然其地址貌似是一樣的(調試過程當中看了下), 可是其實並非同一個只能指針,調試

從其計數不同就能夠看出來,code

 

同理, 其餘相似的也是同樣會構造出新的對象對象

 

可是即便是這樣寫blog

std::shared_ptr<C> p = (std::shared_ptr<C>)this;seo

強制類型轉換過來的, 也是一個新的智能指針指針對象.

 

實際上 

std::shared_ptr<C>(this)

自己就是一個構造新對象的語句

相關文章
相關標籤/搜索