作者:gzshun. 原创作品,转载请标明出处!
来源:http://blog.csdn.net/gzshun
在《C++ Primer中文版第4版》中,有这么一个小节"管理指针成员"。有点好奇,咱也学学,刚开始有点不理解其目的,经过反复验证,才知道所以然。以前一直有个错误的习惯,看书从第一章看到了最后一章,有点愚昧。现在已经把那种不好的习惯给改了,我想学哪一章,哪一节都行,学我想学的部分即可,要不书这么多,还这么厚,看到猴年马月,说不定哪天阿基米德找到支点,把地球给撬起来。
在这本书中,有两种方法来管理指针成员:定义智能指针类和值型类
一、智能指针的引子
每个事件的发生,都有一个因果关系,这里出现了智能指针的解决方案,是处理什么情况呢?也就是管理指针。。。
先来个小例子:
指针共享同一对象
1.一个类中存在一个指针成员;
2.声明A对象,再声明B对象,最后用A对象作为B对象的初始值;(复制构造函数)
3.释放A对象,释放了指针所指的空间;
4.B对象继续访问类中的指针成员???问题来了
#include <iostream>
using namespace std;
class CObj
{
public:
CObj(int *p) : mPtr(p)
{
}
~CObj()
{
delete mPtr;
}
void ShowData() const
{
cout << *mPtr << endl;
}
private:
int *mPtr;
};
int main()
{
int *p = new int(2);
CObj *A = new CObj(p);
CObj B(*A);
cout << "A与B中的指针指向同一个int对象" << endl;
A->ShowData();
B.ShowData();
delete A; //删除指针所指向的内容
cout << "释放指针所指向的空间" << endl;
B.ShowData(); //错误,访问了已经被删除的内容
return 0;
}
执行结果:
A与B中的指针指向同一个int对象
2
2
释放指针所指向的空间
0
这里我看了结果,惊叹了,GCC编译器也优化得太多了,访问被删除的空间都不提示错误,无语。我试过了C语言与C++错误的例子,GCC与G++编译都是成功的,后来网上一搜,有人说:老版本的GCC编译器会提示错误,最新版本的GCC做了优化,数组越界与访问悬垂指针都不报错。
但"B.ShowData();"语句是错误的,必须要避免。
二、定义智能指针类--引入使用计数
虽然叫智能指针类,但也智能不到哪里去。该智能指针负责删除共享对象,用户同样将动态分配的一个对象地址传给了类中的指针。但绝对不能释放指针所指的空间。(不然也不叫智能指针了)
以下是《C++ Primer中文版第4版》书中的一个例子,被我修改了,增加了一些打印信息,更直观的了解智能指针类的使用与目的。
#include <iostream>
using namespace std;
class U_Ptr
{
friend class HasPtr;
int *ip;
size_t use;
U_Ptr(int *p) : ip(p), use(1)
{
}
~U_Ptr()
{
delete ip;
}
};
class HasPtr
{
public:
HasPtr(int *p, int i) : ptr(new U_Ptr(p)), val(i)
{
cout << "默认构造函数" << endl;
}
HasPtr(const HasPtr &orig) : ptr(orig.ptr), val(orig.val)
{
++ptr->use;
cout << "复制构造函数" << endl;
}
HasPtr & operator=(const HasPtr &rhs)
{
++rhs.ptr->use;
if (--ptr->use == 0)
{
cout << "赋值操作符释放ptr指针" << endl;
delete ptr;
}
ptr = rhs.ptr;
val = rhs.val;
return *this;
}
~HasPtr()
{
cout << "调用析构函数" << endl;
if (--ptr->use == 0)
{
delete ptr;
cout << endl << "析构函数释放ptr指针" << endl;
}
}
void GetUse() const
{
cout << "使用计数 = " << ptr->use << endl;
}
private:
U_Ptr *ptr;
int val;
};
int main()
{
int *p = new int(2);
HasPtr A(p, *p);
cout << "创建了A对象: ";
A.GetUse();
cout << endl;
HasPtr B(A);
cout << "创建了B对象: ";
B.GetUse();
cout << endl;
HasPtr C(p, *p);
cout << "创建了C对象: ";
C.GetUse();
cout << endl;
C = A;
C.GetUse();
cout << endl;
return 0;
}
执行结果:
默认构造函数
创建了A对象: 使用计数 = 1
复制构造函数
创建了B对象: 使用计数 = 2
默认构造函数
创建了C对象: 使用计数 = 1
赋值操作符释放ptr指针
使用计数 = 3
调用析构函数
调用析构函数
调用析构函数
析构函数释放ptr指针
三、定义值型类
值型类,类中的指针不会共享同一个对象,对副本所做的改变不会反映到原有对象上。复制构造函数不再复制指针,而是分配一个新的int对象,并初始化该对象以保存被复制对象相同的值。
#include <iostream>
using namespace std;
class U_Ptr
{
friend class HasPtr;
int *ip;
size_t use;
U_Ptr(int *p) : ip(p), use(1)
{
}
~U_Ptr()
{
delete ip;
}
};
class HasPtr
{
public:
HasPtr(const int &p, int i) : ptr(new int(p)), val(i)
{
cout << "调用构造函数" << endl;
}
HasPtr(const HasPtr &orig) : ptr(new int(*orig.ptr)), val(orig.val)
{
cout << "调用复制构造函数" << endl;
}
HasPtr & operator=(const HasPtr &ths)
{
cout << "调用赋值操作符" << endl;
*ptr = *ths.ptr;
val = ths.val;
return *this;
}
~HasPtr()
{
cout << "调用析构函数" << endl;
delete ptr;
}
void ShowData() const
{
cout << "*ptr = " << *ptr << endl
<< "val = " << val << endl;
}
private:
int *ptr;
int val;
};
int main()
{
int *p = new int(2);
HasPtr A(*p, *p);
A.ShowData();
cout << endl;
HasPtr B(A);
B.ShowData();
cout << endl;
HasPtr C(*p, *p);
C = A;
C.ShowData();
cout << endl;
return 0;
}
执行结果:
调用构造函数
*ptr = 2
val = 2
调用复制构造函数
*ptr = 2
val = 2
调用构造函数
调用赋值操作符
*ptr = 2
val = 2
调用析构函数
调用析构函数
调用析构函数
分享到:
相关推荐
C++ 智能指针C++ 智能指针C++ 智能指针
C++中智能指针的设计和使用,能非常经典的境界C++中智能指针。
模板和智能指针(c++) 模板和智能指针(c++)模板和智能指针(c++) 模板和智能指针(c++) 模板和智能指针(c++)
介绍stl中三种智能指针,对于学习STL很有帮助.上次面试就被问到了。
C++学习笔记和实践项目,实践项目包括Json工具类、设计模式的C++实现、消息队列、智能指针,linux下的并发控制工具、线程池,epoll管理器和Mysql连接池、STL容器的快捷输出工具和页面置换算法(FIFO, LRU, LFU)的...
智能指针sp和wp在android c++源码中使用非常频繁,例如IBinder机制,但是它比c++中普通的智能指针要复杂很多,相信不少android学习者如果c++基础不是很扎实的,看起来会比较吃力和枯燥。本人在android 4.2.2源码基础...
结构体指针应用-改写选票系统c++源码.zip结构体指针应用-改写选票系统c++源码.zip结构体指针应用-改写选票系统c++源码.zip结构体指针应用-改写选票系统c++源码.zip结构体指针应用-改写选票系统c++源码.zip结构体指针...
本篇随笔仅作为个人学习《C++ Primer》智能指针一节后的部分小结,抄书严重,伴随个人理解。主要介绍shared_ptr、make_shared、weak_ptr的用法和联系
《Effective Modern C++:改善C++11和C++14的42个具体做法(影印版)(英文版)》中包括以下主题:剖析花括号初始化、noexcept规范、完美转发、智能指针make函数的优缺点;讲解std∷move,std∷forward,rvalue引用和全局...
此仓库是一些自己学习的东西,涉及C++11基础知识,智能指针,内存四区, 数据结构和算法,linux, mysql,
C++学习笔记和常见面试知识点,C++11特性,包括多态、虚表、移动语义、友元函数、符号重载、完美转发、智能指针、const和static、数组指针和指针数组、struct内存对齐、enum和union关键字等等。帮助了解C++的特性,...
如题,我们今天要讲的是 C++11 引入的三种智能指针中的:weak_ptr。 在学习 weak_ptr 之前最好对 shared_ptr 有所了解。如果你还不知道 shared_ptr 是何物,可以看看另一篇文章: 【C++11新特性】 C++11智能指针之...
最近项目中使用boost库的智能指针,感觉智能指针还是蛮强大的,在此贴出自己学习过程中编写的测试代码,以供其他想了解boost智能指针的朋友参考,有讲得不正确之处欢迎指出讨论。当然,使用boost智能指针首先要编译...
自己秋招根据面经和基础.../ 继承 / 多态、引用 & 指针、重载与重写、右值引用、智能指针、整形字面量...... 对于C/C++/C++11/C++14的内容都有涉及,但肯定没法做到100%知识点全覆盖,可以根据自己需要后续添加内容。
介绍:本文辑是对C++中的部分难点专题进行分章的专门讲解,不是一套完整的教材,但可以做为学习C++的参考,这些专题本人都对C++中...C++的String类及其成员函数和智能指针专题 C++的IO(输入输出)专题 C++操作符重载专题
C++入门Demo(相对简单) 基本包括Android中需要的C++点,除了智能指针等,适合入门看。
.zip涵盖C++ Primer 5th、 effective C++ 、 STL api和demos C++ 基础知识与理论、 智能指针、C++11、 Git教程 Linux命令 Unix操作系统(进程、线程、内可下载学习借鉴,你会有所收获。可下载学习借鉴,你会有所收获...
- 学习C++11及其以上的新特性,如auto、lambda表达式、智能指针等; - 学会使用调试工具,如gdb、valgrind等。 ## Java Java是一种广泛应用于企业级开发的高级编程语言,具有跨平台、安全、健壮等特点。学习Java...
主要介绍了 C++11 智能指针之shared_ptr的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下