項目中用到了智能指針,可是要在智能指針指向的類中獲取此類的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)
自己就是一個構造新對象的語句