码迷,mamicode.com
首页 > 编程语言 > 详细

一次测试测试(C++11)智能指针引用的崩溃结论

时间:2017-02-27 18:58:36      阅读:284      评论:0      收藏:0      [点我收藏+]

标签:int   生成   pre   ring   virt   调试   cond   log   map   

项目中用到了智能指针,但是要在智能指针指向的类中获取此类的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 }

 

结论:

在赋值过程中,用形如

std::shared_ptr<C>(this)

的方式取得本指针的shared_ptr指针,会产生新的shared_ptr指针,,,而不是你想要的那个指针(类外定义的那个指针),

虽然其地址貌似是同样的(调试过程中看了下), 但是其实并不是同一个只能指针,

从其计数不一样就可以看出来,

 

同理, 其他类似的也是一样会构造出新的对象

 

但是即使是这样写

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

强制类型转换过来的, 也是一个新的智能指针指针对象.

 

实际上 

std::shared_ptr<C>(this)

本身就是一个构造新对象的语句

 

一次测试测试(C++11)智能指针引用的崩溃结论

标签:int   生成   pre   ring   virt   调试   cond   log   map   

原文地址:http://www.cnblogs.com/lzpong/p/6475731.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!