标签: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)
本身就是一个构造新对象的语句
标签:int 生成 pre ring virt 调试 cond log map
原文地址:http://www.cnblogs.com/lzpong/p/6475731.html