项目中用到了智能指针,但是要在智能指针指向的类中获取此类的shared_ptr指针传给其引用的类,结果出现了问题,

测试代码如下: (包括错误解释)

 //测试 shared_ptr weak_ptr  map<string,shared_ptr>
#include <stdio.h> //pinrtf ...
#include <string> //string ...
#include <map>
#include <memory> //shared_ptr ... class C; class A {
public:
A() { printf("A()\n"); }
~A() { printf("~A()\n"); } std::string a;
std::weak_ptr<C> with;
virtual std::string geta() = ;
}; class A1:public A {
public:
A1(std::string aa) { a = aa; printf("A1(%s)\n",aa.c_str()); };
~A1() { printf("~A1(%s)\n", a.c_str()); } std::string geta() { std::string b = "A1 " + a; return b; }
}; class A2:public A {
public:
A2(std::string aa) { a = aa; printf("A2(%s)\n", aa.c_str()); };
~A2() { printf("~A2()\n"); printf("~A2(%s)\n", a.c_str()); } std::string geta() { std::string b = "A2 " + a; return b; }
}; typedef std::shared_ptr<A> shrA;
typedef std::shared_ptr<A1> shrA1;
typedef std::shared_ptr<A2> shrA2; template<class _ty>
class AA {
public:
AA() { printf("AA()\n"); }
~AA() { printf("~AA()\n"); } typedef std::map<std::string, _ty> Atype;
Atype list;
}; class C
{
public:
C() { printf("C()\n"); }
~C() { printf("~C()\n"); }//在这个析构函数中下断点会发现进入两次的,两次析构
shrA h1, h2;
std::weak_ptr<A> a; void add(shrA h) {
if (h1 == nullptr) {
h1 = h;
//std::shared_ptr<C> p = (std::shared_ptr<C>)this;//此法虽然不会释放内存了,但是引用计数不对(此处是weak_ptr,但是shared_ptr计数也不对的)
h->with = std::shared_ptr<C>(this); //这样写会在赋值的过程中产生一次创建临时对象(包括构造和析构,会释放掉this的内存)
//因为以这种方式写的话,在这里是用this直接生成了shared_ptr,所以引用计数会变成1,导致在此次析构时释放掉内存
//而导致外面的引用指针指向了被释放掉的内存,,,so,崩溃~~
}
else if(h2 == nullptr) {
h2 = h;
h->with = std::shared_ptr<C>(this);//同上
}
printf("C::add %s\n",h->geta().c_str());
}
};
typedef std::shared_ptr<C> shrC; class CC
{
public :
CC() { printf("CC()\n"); }
~CC() { printf("~CC()\n"); } typedef std::map<std::string, std::shared_ptr<C>> Ctype;
Ctype list;
}; int main() {
{
AA<shrA1> aa1;
AA<shrA2> aa2; CC cc; shrA1 a1 = shrA1(new A1("啊"));
auto b = aa1.list.emplace(std::make_pair("a1", a1)); shrA1 a11 = shrA1(new A1("啊啊"));
b = aa1.list.emplace(std::make_pair("a1", a11));//key 重复,放置失败 (b.seond==false) shrA2 a2(new A2("份饭"));
auto b2 = aa2.list.emplace(std::make_pair("a2", a2)); printf("\n----- --------\n");
for (auto p : aa1.list)
printf("%s\n", p.second->geta().data());
printf("\n----- --------\n");
shrC c(new C());
cc.list.emplace("c1", c);
//c->add(a11); c->add a1/a11/a2 都会导致崩溃
c->add(a2);
}
return ;
}

结论:

在赋值过程中,用形如

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)智能指针引用的崩溃结论的更多相关文章

  1. C++11智能指针之std::unique_ptr

    C++11智能指针之std::unique_ptr   uniqut_ptr是一种对资源具有排他性拥有权的智能指针,即一个对象资源只能同时被一个unique_ptr指向. 一.初始化方式 通过new云 ...

  2. c++11 智能指针 unique_ptr、shared_ptr与weak_ptr

    c++11 智能指针 unique_ptr.shared_ptr与weak_ptr C++11中有unique_ptr.shared_ptr与weak_ptr等智能指针(smart pointer), ...

  3. C++11——智能指针

    1. 介绍 一般一个程序在内存中可以大体划分为三部分——静态内存(局部的static对象.类static数据成员以及所有定义在函数或者类之外的变量).栈内存(保存和定义在函数或者类内部的变量)和动态内 ...

  4. 【C++11新特性】 C++11智能指针之weak_ptr

    如题,我们今天要讲的是C++11引入的三种智能指针中的最后一个:weak_ptr.在学习weak_ptr之前最好对shared_ptr有所了解.如果你还不知道shared_ptr是何物,可以看看我的另 ...

  5. 详解C++11智能指针

    前言 C++里面的四个智能指针: auto_ptr, unique_ptr,shared_ptr, weak_ptr 其中后三个是C++11支持,并且第一个已经被C++11弃用. C++11智能指针介 ...

  6. C++11 智能指针

    C++ 11标准库引入了几种智能指针 unique_ptr shared_ptr weak_ptr C++内存管理机制是当一个变量或对象从作用域过期的时候就会从内存中将他干掉.但是如果变量只是一个指针 ...

  7. C++11智能指针

    今晚跟同学谈了一下智能指针,突然想要看一下C++11的智能指针的实现,因此下了这篇博文. 以下代码出自于VS2012 <memory> template<class _Ty> ...

  8. 【C++11新特性】 C++11智能指针之shared_ptr

    C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...

  9. C++11智能指针的深度理解

    平时习惯使用cocos2d-x的Ref内存模式,回过头来在控制台项目中觉得c++的智能指针有点生疏,于是便重温一下.首先有请c++智能指针们登场: std::auto_ptr.std::unique_ ...

随机推荐

  1. 1)Javascript设计模式:Module模式

    最简单的创建对象方法 function User(name) { this.name = name || '' } User.prototype.say = function() { console. ...

  2. p1349星屑幻想

    这道题的原题目我也不知道是什么. 大致题意是有一个图,有些点的权值已确定,要求你确定其他点的权值使所有边两个点的权值的xor和最小,输出所有点的最终权值,输出有spj: 解法是最小割,由于题目要求的使 ...

  3. 绕过网站安全狗拦截,上传Webshell技巧总结(附免杀PHP一句话)

    这篇文章我介绍一下我所知道的绕过网站安全狗上传WebShell的方法. 思路是:修改HTTP请求,构成畸形HTTP请求,然后绕过网站安全狗的检测. 废话不多说,切入正题.... 1.实验环境: Win ...

  4. 【滚动数组】【状压dp】Gym - 100956F - Colored Path

    f(i,j,S)表示到(i,j),且经由的路径上的颜色集合为S的价值的最小值,从上方和左方转移过来即可. 要注意,内存不足,需要滚动数组优化,即使用了map,还是需要. 路径输出的时候,可以再跑一遍d ...

  5. UVa 11456 - Trainsorting

    题目大意:给一个车辆到达车站的序列(按时间先后),可以对车辆进行以下处理:插在队首.插在队尾或者拒绝进站.车站内的车辆必须按照重量大小从大到小排列,问车站内最多能有多少辆车辆? 假设车i是第一个进站, ...

  6. iOS 错误之 NSObject 、CGFloat

    需要添加 #import <Foundation/Foundation.h> #import <UIKit/UIKit.h>

  7. C,C++,VC++有什么区别

    C语言是一种古老而又经久不衰的计算机程序设计语言,大约诞生于上个世纪60年代.由于它的设计有很多优点,多年以来深受广大程序设计人员的喜爱,并逐渐淘汰了很多其它程序设计语言.我们平时使用的大多数软件都是 ...

  8. ExtJs 中的ext.date

    获取当前日期直接用NEW date() Ext.Date英文API http://docs.sencha.com/ext-js/4-1/#!/api/Ext.Date Ext.Date是一个单例类,封 ...

  9. adb server无法启动方法,结束占用端口的进程

    adb server is out of date.  killing...ADB server didn't ACK* failed to start daemon *error: unknown ...

  10. hadoop-1.x的运行实例

    我的环境是hadoop-0.20.2,eclipse:SDK-3.3.2, 源数据为: Apr 23 11:49:54 hostapd: wlan0: STA 14:7d:c5:9e:fb:84 Ap ...