C++ Primer 有感(管理类的指针成员)
C++类的指针成员与其他成员有所不同,指针成员指向一个内存地址,该地址的内存需要我没管理。
我现在分析一下为什么要管理指针成员。
有如下Student类,Student.h如下:
- class Student
- {
- public:
- Student(int *books);
- virtual ~Student();
- int *books;
- };
Student.cpp如下:
- #include "Student.h"
- Student::Student(int *books)
- {
- this->books=books;
- }
- Student::~Student()
- {
- }
在主函数中我如下写:
- #include <iostream>
- #include "Student.h"
- using namespace std;
- int main()
- {
- int *b=new int(34);
- Student s(b);
- delete b;
- cout<<(*(s.books))<<endl;
- return 0;
- }
当我释放掉了b所指的空间,b的地址就不能用了,但是在s中任然可以访问,所以就出现了不可预知的错误
最后输出的结果如下:

这个指针所指的空间需要我们的Student类来管理,因为我们不知道什么时候该释放掉b的空间,如果手动释放掉b的空间,然后再使用Student对象引用该空间的值,就会出现上面的错误。更复杂的情况是使用一个Student对象初始化另外一个Student对象的时候和赋值的时候。
管理指针成员有两种办法
1.定义智能指针类
2.定义值类型
下面分别介绍
1.智能指针
智能指针:一个行为类似指针但也提供其他功能的类。智能指针的一个通用形式接受指向动态分配对象的指针并负责删除掉该对象,用户分配对象,但由智能指针类删除掉它。智能指针类需要实现复制控制成员来管理指向共享对象的指针。只有在撤销了指向共享对象的最后一个智能指针后,才能删除该共享对象。使用计数是实现智能指针类最常用的方式。
计数类的实现
我先设计一个数据类,目的是察看智能指针的效果。数据类就一个数据,int类型,我主要在析构函数中输出删除了该对象。Flag.h头文件:
- class Flag {
- public:
- Flag(int v);
- virtual ~Flag();
- int i;
- };
Flag.cpp源文件:
- #include "Flag.h"
- #include <iostream>
- Flag::Flag(int v) {
- // TODO Auto-generated constructor stub
- i=v;
- }
- Flag::~Flag() {
- std::cout<<"delete the value"<<std::endl;
- }
下面实现记述类:U_Ptr.h文件:
- #include "Flag.h"
- class U_Ptr {
- public:
- friend class Student;
- U_Ptr(Flag *p);
- virtual ~U_Ptr();
- private:
- Flag *books;
- unsigned int use;
- };
U_Ptr.cpp源文件:
- #include "UPtr.h"
- U_Ptr::U_Ptr(Flag *p) {
- this->books=p;
- this->use=1;
- }
- U_Ptr::~U_Ptr() {
- delete books;
- }
这个类设置Student类为它的友元,以便在Student类中访问该类的私有成员。该类接收一个Flag的指针,该内存在其他地方分配,由U_Ptr类来管理,当该类被释放的时候回收Flag指针所指内存。
下面我完成智能指针类Student,该类决定在什么样的情况下删除Flag指针所分配的内存。
Student.h头文件:
- #include "UPtr.h"
- #include "Flag.h"
- class Student {
- public:
- Student(Flag *p);
- Student(const Student &s);
- Student& operator=(const Student &s);
- int getValue();
- void setValue(int number);
- virtual ~Student();
- private:
- U_Ptr *ptr;
- };
该类包含了一个U_Ptr对象的指针,在这个类中,要对复制与赋值进行控制。
Student.cpp源文件:
- #include "Student.h"
- Student::Student(Flag *p) {
- this->ptr=new U_Ptr(p);
- }
- Student::Student(const Student &s)
- {
- this->ptr=s.ptr;
- ++ptr->use;
- }
- Student& Student::operator=(const Student &s)
- {
- ++s.ptr->use;
- if(--ptr->use==0)
- {
- delete ptr;
- }
- ptr=s.ptr;
- return *this;
- }
- int Student::getValue()
- {
- return (ptr->books)->i;
- }
- void Student::setValue(int number)
- {
- (ptr->books)->i=number;
- }
- Student::~Student() {
- if(--ptr->use==0)
- {
- delete ptr;
- }
- }
在构造函数中,为ptr指针分配内存,但是这个内存在什么时候释放掉要看该ptr的use的计数,当use为0的时候,说明没有其他的Student类共享该ptr所指内存,这时就释放内存。
在赋值的时候,先将右值的计数加一,本对象的计数应该减一,并且判断这时是否应该释放该对象,然后将右值的ptr赋值给本对象。这样如果是相同的对象赋值的话,有安全的保障。如果先减一,刚好计数为1,会释放内存,然后将计数加一。
在主函数中执行下面的代码会得到我希望的结果:
- #include <iostream>
- using namespace std;
- #include "Flag.h"
- #include "Student.h"
- int main() {
- Flag *f=new Flag(43);
- Student s1(f);
- Student s2(s1);
- return 0;
- }
打印出 delete the value.
2.定义值类型
这种方法比较简单,看代码了:
Human.h类就是这样的类:
Human.h
- class Human {
- public:
- Human(int value);
- Human(const Human &value);
- Human& operator=(const Human &value);
- virtual ~Human();
- private:
- int *ip;
- };
Human.cpp
- #include "Human.h"
- Human::Human(int value) {
- // TODO Auto-generated constructor stub
- ip=new int(value);
- }
- Human::Human(const Human &value) {
- // TODO Auto-generated constructor stub
- ip=new int(*(value.ip));
- }
- Human& Human::operator=(const Human& value)
- {
- *ip=*(value.ip);
- return *this;
- }
- Human::~Human() {
- // TODO Auto-generated destructor stub
- delete ip;
- }
在构造函数中为指针分配内存,在析构函数中释放内存,在赋值操作中改变指针所指内容的值而不是指针的值。
C++ Primer 有感(管理类的指针成员)的更多相关文章
- C++ Primer 有感(类)
1.在类内部,声明成员函数时必需 的,而定义成员函数则是可选的.在类内部定义的函数默认为inline. 2.const成员函数不能改变其所操作的对象的数据成员.const必须同时出现在声明和定义中,若 ...
- C++ Primer 学习笔记_57_类和数据抽象 --管理指针成员
复印控制 --管理指针成员 引言: 包括指针的类须要特别注意复制控制.原因是复制指针时.一个带指针成员的指针类 class HasPtr { public: HasPtr(int *p,int i): ...
- 【c++】类管理指针成员
c++编程提倡使用标准库,一个原因是标准库大胆减少对指针的使用.但是许多程序是离不开指针的.包含指针的类需要特别注意复制控制,原因是复制指针时只复制指针中的地址,而不复制指针所指向的对象.这样当把一个 ...
- C++ 带有指针成员的类处理方式
在一个类中,如果类没有指针成员,一切方便,因为默认合成的析构函数会自动处理所有的内存.但是如果一个类带了指针成员,那么需要我们自己来写一个析构函数来管理内存.在<<c++ primer&g ...
- C++智能指针管理类
1.程序员明确的进行内存释放 对于c++程序员,最头脑的莫过于对动态分配的内存进行管理了.c++在堆上分配的内存,需要程序员负责对分配的内存进行释放.但有时内存的释放看起来并不件很轻松的事,如下程序 ...
- 类1(this指针/const成员函数/类作用域/外部成员函数/返回this对象的函数)
假设我们要设计一个包含以下操作的 Sales_data 类: 1.一个 isbn 成员函数,用于返回对象的 book_no 成员变量 2.一个 combine 成员函数,用于将一个 Sales_dat ...
- C++管理指针成员
1.C++中一般採用以下三种方法之中的一个管理指针成员: (1)指针成员採取常规行为. 这种类具有指针的全部缺陷:具有指针成员且使用默认复制构造函数和赋值操作符,无法避免悬垂指针(两个对象的指针成员指 ...
- YTU 2636: B3 指向基类的指针访问派生类的成员函数
2636: B3 指向基类的指针访问派生类的成员函数 时间限制: 1 Sec 内存限制: 128 MB 提交: 433 解决: 141 题目描述 领导类(Leader)和工程师类(Engineer ...
- 15.含有指针成员的类的拷贝[ClassCopyConstructorWithPointerMember]
[题目] 下面是一个数组类的声明与实现.请分析这个类有什么问题,并针对存在的问题提出几种解决方案. C++ Code 123456789101112131415161718192021222324 ...
随机推荐
- cassandra 3.x官方文档(5)---探测器
写在前面 cassandra3.x官方文档的非官方翻译.翻译内容水平全依赖本人英文水平和对cassandra的理解.所以强烈建议阅读英文版cassandra 3.x 官方文档.此文档一半是翻译,一半是 ...
- 潜谈IT从业人员在传统IT和互联网之间的择业问题(上)-传统乙方形公司
外包能去吗?项目型公司如何?甲方比乙方好?互联网公司就一定好吗? 相信许多从业者在经历了3-5年的工作期后都会带着这样的疑问或者疑惑. 2012年-2014年间,曾经面试过500人,亲身面试的也有15 ...
- [BBS]搭建开源论坛之JForum安装使用札记
本文作者:sushengmiyan 本文地址:http://blog.csdn.net/sushengmiyan/article/details/47761303 目录 目录 BBS搭建开源论坛之JF ...
- Hadoop2动态调整Log级别-以datanode的heartbeat log为例
在Hadoop中,有些log信息在正常情况下是不打印出来的.比如datanode发送heartbeat的日志. 代码位于BPServiceActor#sendHeartBeat方法中,如下图: 由于默 ...
- 在java程序中实现发送邮件的功能
最近比较忙,在做一个人事管理系统的项目,在这项目需求中,需要一个发送邮件的功能.这个时候我们可以使用javamail的jar包来实现完美需要的功能,在这里简单的分享一个最基础的发邮件功能. 首先我们需 ...
- python 3 dict函数 神奇的参数规则
>>> dict({1:2},2=3)SyntaxError: keyword can't be an expression>>> dict({1:2},**{2: ...
- Android自定义处理崩溃异常
用过安卓手机的用户以及安卓开发者们会时长碰到程序异常退出的情况,普通用户遇到这种情况,肯定非常恼火,甚至会骂一生垃圾软件,然后卸载掉.那么开发者们在开发过程中遇到这种情况给怎么办呢,当然,你不可能世界 ...
- numpy教程:排序、搜索和计数
http://blog.csdn.net/pipisorry/article/details/51822775 numpy排序.搜索和计数函数和方法.(重新整合过的) ],, , ], [, , ]] ...
- Java进阶(四十一)多线程讲解
Java多线程讲解 前言 接到菜鸟网络的电话面试,面试官让自己谈一下自己对多线程的理解,现将其内容整理如下. 线程生命周期 Java线程具有五种基本状态 新建状态(New):当线程对象创建后,即进入了 ...
- Android 深入理解Loader机制 让APP轻装上阵
本文简书同步发布,谢谢关注. http://blog.csdn.net/sk719887916/article/details/51540610 Android开发者都经历过APP UI开发不当 会造 ...