• 一次测试测试(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()
    "); }
     12     ~A() { printf("~A()
    "); }
     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)
    ",aa.c_str()); };
     22     ~A1() { printf("~A1(%s)
    ", 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)
    ", aa.c_str()); };
     30     ~A2() { printf("~A2()
    "); printf("~A2(%s)
    ", 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()
    "); }
     43     ~AA() { printf("~AA()
    "); }
     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()
    "); }
     54     ~C() { printf("~C()
    "); }//在这个析构函数中下断点会发现进入两次的,两次析构
     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
    ",h->geta().c_str());
     71     }
     72 };
     73 typedef std::shared_ptr<C> shrC;
     74 
     75 class CC
     76 {
     77 public :
     78     CC() { printf("CC()
    "); }
     79     ~CC() { printf("~CC()
    "); }
     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("
    -----  --------
    ");
    102         for (auto p : aa1.list)
    103             printf("%s
    ", p.second->geta().data());
    104         printf("
    -----  --------
    ");
    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)

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

  • 相关阅读:
    WebService基于SoapHeader实现安全认证
    js中SetInterval与setTimeout用法
    Fiddler 教程
    jQuery 的 serializeArray()、serialize() 方法
    Javascript中Array.prototype.map()详解
    MS DOS 命令大全
    Chrome的JS调试工具
    jquery插件之DataTables 参数介绍
    C#中的Params、ref、out的区别
    C#记录日志、获取枚举值 等通用函数列表
  • 原文地址:https://www.cnblogs.com/lzpong/p/6475731.html
Copyright © 2020-2023  润新知