下面很多例子用到process函数,process定义如下:

void process(shared_ptr<int> ptr){//使用ptr}//ptr离开作用域,被销毁

1.定义不当的

#include <iostream>
#include <string>
#include <memory>
using namespace std;
int main()
{
shared_ptr<int> p(new int(123));
shared_ptr<int> p1(p);
//下面定义可以通过编译,但是不能使用use_count成员函数
//也可以解引用,结果是1,鬼知道是咋回事,所以给shared_ptr赋值的对象也是shard_ptr时候,别多转换代码,否则错误一大堆,还不能正常使用。
//后来又查书,下面的代码是利用p构造一个新的shared_ptr赋值给p2,但是不能把临时构造的在用来临时构造,否则不能用use_count函数
shared_ptr<int> p2(shared_ptr<int>(p));//圆括号内直接放p就可以了。
cout << p.use_count() << endl;
cout << p1.use_count() << endl;
cout << p2.use_count() << endl;return 0;
}
~
~      

再看一个临时构造的例子,我自己得到的结论是,若果用一个shared_ptr对象p1去临时构造一个shared_ptr对象p2(p2 = shared_ptr<int>(p1)),p1可以正常使用,包括解引用,get()和use_count()成员,但是如果继续用p2用相同方法构造一个p3,那么p3就不能正常使用了。解引用,get和use_count成员都会出错的。

#include <string>
#include <iostream>
#include <memory>
using namespace std;
void process(shared_ptr<int> ptr)
{cout << "execute the program." << endl;cout << "print :" << *ptr << endl;cout << "delete ptr automatically.." << endl;cout << ptr.use_count() << endl;cout << ptr.get()<< endl;shared_ptr<int> p2(shared_ptr<int>(ptr));//下面的2语句就会出错,也就是说,如果ptr是临时构造的,然后再用ptr临时构造,就会出问题,不能使用use_count和get这两个成员函数,而且,解引用也会报错。 //cout << p2.use_count() << endl;//cout << p2.get() << endl;cout << "p2 's value is:"<<*p2 << endl;
}int main()
{
shared_ptr<int> p(new int(42));
cout << "p's get is:" << p.get() << endl;
process(p);
process(shared_ptr<int>(p));return 0;
}
~     
shared_ptr<int> p(new int(42));
shared_ptr<int> p2 = (shared_ptr<int>(p));
shared_ptr<int> p3 = shared_ptr<int>(p2);
shared_ptr<int> p4(shared_ptr<int>(p3));
//用等号一般都是没问题(例如前三行),但是如果是临时构造出来的(第四行),使用p4就会出问题

2.关于c++primer5th  414页一段代码说是可以销毁指针,结果自己实验是不可以销毁的。改成下面的是可以销毁的,

#include <iostream>
#include <string>
#include <memory>
using namespace std;
int main()
{
shared_ptr<int> p(new int(42));
int *q = p.get();
{
int * k = new int;
k = q;
delete k;
}
cout << *q << endl;
cout << *p << endl;

{
auto p = new int(1234);
auto sp = make_shared<int>();{shared_ptr<int> p1 = shared_ptr<int>(p);}

上面这个代码也可以释放p1,p1释放,p也就释放了。

auto p = new int(1234);
auto sp = make_shared<int>(1111);{shared_ptr<int> p1 = shared_ptr<int>(sp);}

上面虽然是利用sp构造一个shared_ptr,但是p1也是指向sp的,最后在块内(打括号内)引用计数是2

但是,如果按照下面的构造方式,就会报错:

auto sp = make_shared<int>(1111);{shared_ptr<int> p1(shared_ptr<int>(sp));}

大括号内,执行p1.get()和p1.use_count()都会报错。解引用p1会得到1,而不是我们期望的1111.为什么?

所以,不能利用一个智能指针构造另一个智能指针。

修改如下,就可以,不调用构造函数,用=就可以:

auto sp = make_shared<int>(1111);{shared_ptr<int> p1 = shared_ptr<int>(sp);}

3.用get()返回的指针构造一个临时的shared_ptr(例如 p3 = shared_ptr<int>(get返回的指针)),那么这个p3(用get返回值构造出来的指针也会出问题)


#include <string>
#include <iostream>
#include <memory>
using namespace std;int main()
{
shared_ptr<int> p(new int(42));
int *q = p.get();{
shared_ptr<int> k(shared_ptr<int>(q));
cout << k.use_count() << endl;  //为啥这里会报错?
}//cout << *q << endl;
return 0;
}
~
~
~    

g++编译器报错如下:

r@r:~/coml/c++/12/12.1/12.1.3/ex$ g++ ex1.cc -o 123
ex1.cc: In function ‘int main()’:
ex1.cc:14:11: error: request for member ‘use_count’ in ‘k’, which is of non-class type ‘std::shared_ptr<int>(std::shared_ptr<int>)’14 | cout << k.use_count() << endl;

有时候会如下报错,

free(): double free detected in tcache 2
Aborted (core dumped)

综上所述,get()返回值来构造一个shared_ptr大多数不会正确执行的。

再比如,process定义如下

void process(shared_ptr<int> ptr)
{
...
}
shared_ptr<int> p(new int(42));

那么我们执行

process(shared_ptr<int>(p.get()));

会出什么问题?

首先,利用shared_ptr<int>(p)来够早shared_ptr,那么p必须是动态指针,而不是普通指针,利用普通指针构造的对象将不会正确地构造处shared_ptr,这就是为什么不能利用get()返回值来初始化shared_ptr的原因所在。更不能给shared_ptr赋值。

正如c++primer5th,414页有这么一句话:

其次,用get()返回值得到的shared_ptr不是一个正确的shared_ptr,将不会形成正确的动态对象共享,因为参数不正确参数不是一个动态内存指针,所以编译器会利用shared_ptr<int>(p.get())新构造出来的指针和原来的指针p是两个不同的对象(编译器会认为p和新构造出来的对象是两个不相干的shared_ptr,虽然它们相等),而非共享一个对象,所以p和ptr(新构造出来传给ptr了)的是两个不同的对象,两个引用计数都是1。当process调用以后,ptr的引用计数是0,所管理的内存地址被释放,而此内存就是p管理的。p称为一个空悬指针的shared_ptr。

再次,再看一个get()构造shared_ptr的例子:

#include <iostream>
#include <vector>
#include <string>
#include <memory>
using namespace std;
void process(std::shared_ptr<int> ptr)
{std::cout << "inside the process function:" << ptr.use_count() << "\n";
}int main()
{std::shared_ptr<int> p(new int(42));/*** @brief   std::shared_ptr<int>(p.get()) construct a temporary shared_ptr* and copy it*          to the parameter.However it is not a copy of p. As a result, at* end of this*          main function p will free the memory that has been freed inside* process ().*          That's why "double freed or corruption" was generated.*/process(std::shared_ptr<int>(p.get()));return 0;
}
~
~
~                                                                                                                                                                                                  

上面代码g++编译器会报错如下:

inside the process function:1
p 's use_count is:
1
free(): double free detected in tcache 2
Aborted (core dumped)

double free tetected in tcache

最后在看一个get()得到的普通指针例子:

#include <iostream>
#include <vector>
#include <string>
#include <memory>
using namespace std;
void process(std::shared_ptr<int> ptr)
{std::cout << "inside the process function:" << ptr.use_count() << "\n";
}int main()
{
auto sp = make_shared<int>();
auto p  = sp.get();
delete p;return 0;
}
~
~
~     
double free or corruption (out)
Aborted (core dumped)

结论:get得到的指针不能delete,也就是说当delete p执行后,sp.use_count()仍然为1,但是已经被释放。main()函数结束的时候,程序会递减sp引用计数,sp引用计数会为0,那么此时sp指向的对象有一次被释放,但是前面已经被释放了,所以会报错。自由空间被释放2此会破坏自由空间。  也就是double free or corruption.....

4.


#include <string>
#include <iostream>
#include <memory>
using namespace std;int main()
{
shared_ptr<int> p(new int(42));
int *q = p.get();{
//下面这句和shared_ptr<int> k(shared_ptr<int>(p));有啥区别,为啥如果下面这句对,本行这句错?
//自己猜测是,本行这句是用p临时构造的,赋值给k,理论上临时构造的也是赋值给k,k也是指向p的
//这个是构造和=(拷贝)当然不一样,区别大,慢慢研究吧shared_ptr<int> k = shared_ptr<int>(p);
cout << *k << endl;
cout << k.use_count() << endl;
}
//cout << *q << endl;
return 0;
}
~
~    

5.c++primer 5th,习题12.12

(a)是合法的,process需要一个shared_ptr参数,sp也是一个shared_ptr对象,完全可以的

并且在调用过程中,ptr的use_count()为2,值为0(值初始化)

(b)不合法,不能把普通指针,转换为智能指针.g++编译器,会报错,如下:

could not convert ‘(operator new(4), (<statement>, ((int*)<anonymous>)))’ from ‘int*’ to ‘std::shared_ptr<int>’

(c)不合法,不能把普通指针转换为只能指针,g++编译器会报错如下:

error: could not convert ‘p’ from ‘int*’ to ‘std::shared_ptr<int>’

(d)合法。但不好。调用结束后构建的临时对象会被销毁,所指向的内存会被释放。

6.在看一个智能指针的错误使用

#include <iostream>
#include <string>
#include <memory>
using namespace std;
int main()
{
int *p = new int(1234);
//我个人的理解是,shared_ptr<int>(p)是临时构造的,传递给shared_ptr的构造函数后,那么构造函数用完后就把这个临时变量释放了,这个临时变量和p1都是是指向原来p指向的对象的,所以p1构造完毕后p也就释放掉了。也就是执行完构造函数后,p就成为空悬指针了,指向它的p1也没有意义了。改正看绿色字体
shared_ptr<int> p1(shared_ptr<int>(p));//cout << p1.use_count() << endl;
//cout << p1.get() << endl;
cout << *p1 << endl;
return 0;
}
~
~   

但是,如果执行玩p1的构造函数后,p会被释放,为何main()函数return前还是可以继续打印出p的指向的值(1234) 呢?

p1的值自从执行完shared_ptr<int> p1(shared_ptr<int>(p))后确实已经变成1了,而不是期望的1234

还有,如果改成下面的形式,会完全正确的。是不是因为shared_ptr<int>做构造函数参数,那么构造函数执行完毕,释放内存了?

而如果是换成是new分配的就不会出现这问题,因为new分配的只要不delete就永久存在?所以得出结果,临时构造出来的智能指针不能做函数参数....是吗?

如果说是因为构造函数释放了p,但是构造后为啥p还是可以解引用出原来的值的?如果说是没有释放,为何p1就已经被破坏了?这只能有一个解释,那就是下面代码构造处的p1是独立于p的另一个备份。也就是shared_ptr<int>(p)是开辟了一个新的空间,

指向构造函数的参数的,但是构造完毕后,被释放了。除此之外,我实在想不出其它可能了。

所以。要构造就用内置指针,

int *p = new int(1234);
shared_ptr<int> p1(p);

下面这句是不对的。

shared_ptr<int> p1(shared_ptr<int>(p));

如果用shared_ptr,就用=复制

shared_ptr<int> p1 = shared_ptr<int>(p);

运行结果是:1,而不是1234

而且p1.use_count()和p1.get()均会报错,g++提示如下错误:

6.cc: In function ‘int main()’:
6.cc:10:12: error: request for member ‘use_count’ in ‘p1’, which is of non-class type ‘std::shared_ptr<int>(std::shared_ptr<int>)’10 | cout << p1.use_count() << endl;|            ^~~~~~~~~
6.cc:11:12: error: request for member ‘get’ in ‘p1’, which is of non-class type ‘std::shared_ptr<int>(std::shared_ptr<int>)’11 | cout << p1.get() << endl;|            ^~~

稍微总结下吧,当我们定义一个只能指针时候,例如

shared_ptr<int> p(q);

这里q要么是一个new 分配的表达式,要么是一个shared_ptr指针(但不能是临时用内置指针构造的shared_ptr),如果相用内置指针来构造一个临时的shared_ptr传递传递给一个智能指针,只能用=拷贝,而不是调用智能指针的构造函数,如下:

int *q = new int(1234);
shared_ptr<int> p = shared_ptr<int>(q);但是不能下面这样写:
int *q = new int(1234);
shared_ptr<int> p(shaared_ptr<int>(q));
如果这样写了,*p会得到1(不知道为啥),p.use_count()和p.get()都会报错(也不知道为啥)

增加部分,下面是unique_ptr的几个例子,unique_ptr的定义类似于shared_ptr

#include <iostream>
#include <memory>
#include <string>
using namespace std;
int main()
{unique_ptr<int> p1(new int(3123));//用内置指针去构造unique_ptr,shared_ptr非常类似cout << *p1 << endl;unique_ptr<int> p2(p1.release());//把p1的值给p2,p1.release()返回p1的指针cout << *p2 << endl;//一会可以用这个动态指针构造一个shared_ptr或者unique_ptrint *k = new int(1234);
//用k构造一个shared_ptr,完全可以,但是用非动态指针是不可以的shared_ptr<int> p4(k);cout << *p4 << endl;
//pi是非动态指针,不可以用来初始化(用构造函数初始化)智能指针,但是pi2可以的int ix =1024,*pi =&ix,*pi2 = new int(2048);typedef unique_ptr<int> IntP;
//下面这句是不可以的,ix不是动态指针//IntP p0(ix);   不合法
//下面当然可以IntP p3(pi2);cout << *p3 << endl;
//下面当然可以的IntP p5(new int(2048));cout << *p5 << endl;
//下面这个当然不可以,普通指针是不可以的//IntP p6(pi);
//下面不可以//IntP p7(&ix);
//下面这个不可以,get()不能初始化智能指针//IntP p8(pi2.get());return 0;
}

关于混合使用智能指针和内置指针的自己的问题和自己的见解(问题搜集中)这个帖子有待解决的问题相关推荐

  1. vivi采集php,php源码:VIVI万能小偷程序1.5 智能采集不求人(内置2条采集规则)

    好东西介绍: Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is se ...

  2. oracle 内置程序包,建立程序包的方法,程序包中使用游标,常用程序包

    文章目录 1. 程序包 1.1 程序包定义 1.2 程序包创建 1.3 程序包中的游标 1.4 有关程序包的信息 2. 内置程序包 3. DBMS_JOB包 4. UTL_FILE包 1. 程序包 1 ...

  3. python内置函数之map函数的水桶效应------计算几个列表中相同位置的数据的和

    与内置函数zip()都是水桶效应 lst1 = [1, 3, 5, 7] lst2 = [2, 4, 6, 8, 10] m = map(lambda x, y, z: x + y+ z, lst1, ...

  4. 微信内置浏览器在使用video标签时(安卓)默认全屏的原因及解决办法

    根据X5论坛得到的答案是:设计如此. 腾讯真是越来越嚣张了,一家独大后用户体验都不注重了(不给程序员留活路). 听说有个申请加入vdeo白名单的,域名验证后就可以解决默认全屏(反正我是没见过申请入口, ...

  5. 指针辨析:悬垂指针、哑指针、野指针、智能指针

    原文地址:https://blog.csdn.net/zhaojinjia/article/details/8770989 悬垂指针: 1:提出的原因: 请看下面的代码片段: int *p=NULL; ...

  6. 华为鸿蒙内置,内置鸿蒙系统,华为生态产品海雀智能摄像头Pro体验

    提起华为鸿蒙系统,估计很多人都不陌生,作为一款分布式操作系统,目前已经在华为智慧屏.华为手表.九阳.美的等产品中内置了鸿蒙系统,手机鸿蒙系统目前正在内测,估计很快大多数华为荣耀手机都可以升级鸿蒙系统了 ...

  7. 鸿蒙系统摄像头,内置鸿蒙系统,华为生态产品海雀智能摄像头Pro体验

    提起华为鸿蒙系统,估计很多人都不陌生,作为一款分布式操作系统,目前已经在华为智慧屏.华为手表.九阳.美的等产品中内置了鸿蒙系统,手机鸿蒙系统目前正在内测,估计很快大多数华为荣耀手机都可以升级鸿蒙系统了 ...

  8. 华为智能摄像头pro鸿蒙系统,内置鸿蒙系统,华为生态产品海雀智能摄像头Pro体验...

    华为生态链产品,自然是支持华为link的,通过华为智慧生活APP客户端,可以直接添加设备,进行设备的绑定设置等,非常的方便. 作为华为生态产品,这款海雀智能摄像头Pro内置强大的海思处理器芯片,具有强 ...

  9. 附录 D:保护 Active Directory 中的内置 Administrator 帐户的安全

    https://docs.microsoft.com/zh-cn/windows/security/identity-protection/access-control/active-director ...

最新文章

  1. 李飞飞谈AI医疗:为什么我要从监督医生洗手开始做起?
  2. vim 记录阅读信息
  3. [网络安全自学篇] 五十八.Windows安全缺陷利用之再看CVE-2019-0708及反弹shell防御措施
  4. 《小马哥Spring Cloud系列》十五:分布式应用追踪-视频笔记
  5. JS HTTP 请求库哪家强?Axios,Request,Superagent,Fetch 还是 Supertest
  6. SpriteKit Advanced —如何构建2,5D游戏(第一部分)
  7. 彻底禁用chrome请停用以开发者模式运行的扩展程序弹框
  8. DDD(领域驱动设计)
  9. 微软警告:警惕新型勒索软件 PonyFinal,已现身印度、伊朗和美国
  10. Memcache分组和同步机制的实现
  11. vim 保存文件的回车换行模式
  12. 爬取企业信息-企业信用信息查询系统-天眼查爬虫
  13. java nas_NAS对家庭来说有什么用处?
  14. 十大常见食物让牙齿越吃越白。
  15. Elasticsearch+Kerberos认证
  16. 阿里安全潘多拉实验室首先完美越狱苹果iOS 11.2
  17. COLA之架构演变(一)
  18. Nginx 最实用的配置技巧!速看
  19. 调节e18-d80nk的测量距离_教程 | GOM数字图像处理三维光学测量系统(ARAMIS) 的设备标定方法...
  20. CF221C Circling Round Treasures

热门文章

  1. UESTC 1851 Kings on a Chessboard
  2. Oracle中DUMP转储方法
  3. 牛客网(剑指offer) 第八题 跳台阶
  4. 【python数据挖掘课程】十八.线性回归及多项式回归分析四个案例分享
  5. 要想提高工作效率,请拒绝做这7种事
  6. 【数据结构与算法】之深入解析“迷宫中离入口最近的出口”的求解思路与算法示例
  7. 【数据结构与算法】之深入解析“排列序列”的求解思路与算法示例
  8. HarmonyOS之LED灯和振动器Vibrator的功能和使用
  9. iOS之深入解析Objective-C和Swift初始化
  10. PyTorch报错No module named ‘transforms‘