[c++] 面向对象课程(二)-- 带指针类的设计
class with pointer menbers
string_test.cpp
1 #include "string.h"
2 #include <iostream>
3
4 using namespace std;
5
6 int main()
7 {
8 String s1("hello");
9 String s2("world");
10
11 String s3(s2);
12 cout << s3 << endl;
13
14 s3 = s1;
15 cout << s3 << endl;
16 cout << s2 << endl;
17 cout << s1 << endl;
18 }
string.h
1 #ifndef __MYSTRING__
2 #define __MYSTRING__
3
4 class String
5 {
6 public:
7 String(const char* cstr=0);
8 String(const String& str);
9 String& operator=(const String& str);
10 ~String();
11 char* get_c_str() const { return m_data; }
12 private:
13 char* m_data;
14 };
15
16 #include <cstring>
17
18 inline
19 String::String(const char* cstr)
20 {
21 if (cstr) {
22 m_data = new char[strlen(cstr)+1];
23 strcpy(m_data, cstr);
24 }
25 else {
26 m_data = new char[1];
27 *m_data = '\0';
28 }
29 }
30
31 inline
32 String::~String()
33 {
34 delete[] m_data;
35 }
36
37 inline
38 String& String::operator=(const String& str)
39 {
40 if (this == &str)
41 return *this;
42
43 delete[] m_data;
44 m_data = new char[ strlen(str.m_data) + 1 ];
45 strcpy(m_data, str.m_data);
46 return *this;
47 }
48
49 inline
50 String::String(const String& str)
51 {
52 m_data = new char[ strlen(str.m_data) + 1 ];
53 strcpy(m_data, str.m_data);
54 }
55
56 #include <iostream>
57 using namespace std;
58
59 ostream& operator<<(ostream& os, const String& str)
60 {
61 os << str.get_c_str();
62 return os;
63 }
64
65 #endif
注意的点
- string_test.cpp:11拷贝构造,14拷贝赋值
- string.h:8拷贝构造(构造函数接受自己),9拷贝赋值,10析构函数
- 不知道将来要创建的对象多大,所以只放一根指针,再动态创建空间放对象
- 类中带指针,要关注三个特殊函数(Big Three)
- 结束符号“\0”判断字符串结束
- 21判断是否空指针
- 22:new:,动态分配一块内存
- 31-35:delete,析构函数,防止内存泄露,变量离开作用域时自动调用
- 11的get_c_str()是为了配合输出函数
拷贝构造(copy ctor)
- String a("Hello"); String b("World"); b = a;
- 如果没有构造拷贝,会发生b和a的指针都指向“Hello”,“World”没有指针指向,导致内存泄露
- 而且a、b一个改动会影响另一个,别名在编程中是危险的事
- 这种拷贝方式称为“浅拷贝”,是编译器的默认版本
- copy ctor 实现“深拷贝”,创建足够的新空间存放蓝本
- String s2(s1); 与 String s2 = s1; 效果相同
拷贝赋值(copy op =)
- String s1("hello"); String s2(s1); s2 = s1;
- 过程:43删除左值--44开辟新空间--45拷贝右值
- 40-41:检测自我赋值(self assignment),来源端和目的端是否相同
- 这步的意义不只是提高效率,不这样写会出错
- 因为43会把原空间删掉,导致45行复制的时候访问空指针
栈(stack)和堆(heap)
- {Complex c1(1,2);}
- {Complex* p = new Complex(3);
- delete p;}
- stack:存在于某作用域(scope)的一块内存空间,调用函数时,函数本身即形成一个stack用来防止它接受的参数,以及返回地址,离开作用域后,析构函数被自动调用(aoto object)
- heap:system heap,操作系统提供的一块global内存空间,程序可以动态分配(dynamic allocated)从中获得若干区域,使用完后需手动释放空间
- {static Complex c1(1,2);}
- 静态对象,离开作用域后对象仍存在,组用域是整个程序
- 全局对象,写在任何作用域之外(全局作用域之中),也可看做一种静态对象
- new:先分配memory,再调用ctor,分解为以下三个函数
- void* mem = operator new(sizeof(Complex)); // 分配内存,operator new调用malloc(n)
- p = static_cast<Complex*>(mem); // 转型
- p->Complex::Complex(1,2); // 构造函数,Complex::Complex(pc,1,2);
- delete:先调用析构函数,再释放内存
- String::~String(p); // 把字符串里面动态分配的内存删掉(字符串本身只是指针m_data)
- operator delete(p); // 内部调用free(p),删掉字符串本身的指针
new到底分配多少内存
- 调试模式下加上debug header 32byte,正常模式下中间为数据(一根指针4byte),上下为cookies 2*4byte,凑够16的倍数
- 动态分配所得的array
- new []:array new
- delete[]:array delete
- array new 一定要搭配 array delete
- String* p = new String[3]; delete[] p; // 唤起3次dtor
- String* p = new String[3]; delete p; // 唤起1次dtor,另外2个指针指向的动态内存数据无法删除(注意指针是可以删除的)
- 虽然new complex的时候不会产生此问题,但也要注意搭配使用,养成好习惯
参考:
const在函数前面与后面的区别
https://blog.csdn.net/qq_25800311/article/details/83054129
[c++] 面向对象课程(二)-- 带指针类的设计的更多相关文章
- C++之不带指针类的设计——Boolean
经典的类设计分类 带指针类 不带指针类 Header文件的布局 #ifndef __COMPLEX__ #define __COMPLEX__ #include <iostream.h> ...
- python笔记20(面向对象课程二)
今日内容 类成员 成员修饰符 内容回顾 & 补充 三大特性 封装 函数封装到类 数据封装到对象 * class Foo: def __init__(self,name,age): self.n ...
- java 面向对象(一):类与对象
1.面向对象学习的三条主线: * 1.Java类及类的成员:属性.方法.构造器:代码块.内部类 * * 2.面向对象的大特征:封装性.继承性.多态性.(抽象性) * * 3.其它关键字:this.su ...
- Lua面向对象之二:类继承
1.类继承 ①代码 Sharp = { } --① 父类 function Sharp:new() local new_sharp = { } self.__index = self --②,self ...
- Expo大作战(二十七)--expo sdk api之Util(expo自带工具类),tackSnapshotAsync,Svg,SQLite
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- 【视频开发】OpenCV中Mat,图像二维指针和CxImage类的转换
在做图像处理中,常用的函数接口有OpenCV中的Mat图像类,有时候需要直接用二维指针开辟内存直接存储图像数据,有时候需要用到CxImage类存储图像.本文主要是总结下这三类存储方式之间的图像数据的转 ...
- php课程 12-38 php的类的构造方法和析构方法怎么写
php课程 12-38 php的类的构造方法和析构方法怎么写 一.总结 一句话总结:a.__construct(参数){},__destruct(){},b.如果类中的一个方法和类名相同,则该方法为构 ...
- Python 基础 面向对象之二 三大特性
Python 基础 面向对象之二 三大特性 上一篇主要介绍了Python中,面向对象的类和对象的定义及实例的简单应用,本篇继续接着上篇来谈,在这一篇中我们重点要谈及的内容有:Python 类的成员.成 ...
- solr与.net系列课程(二)solr的配置文件及其含义
solr与.net系列课程(二)solr的配置文件及其含义 本节内容还是不会涉及到.net与数据库的内容,但是不要着急,这都是学时solr必学要掌握的东西,solr可不是像其他的dll文件一样,只需 ...
随机推荐
- AgileConfig轻量级配置中心1.3.0发布,支持多用户权限控制
AgileConfig 当初是设计给我自己用的一个工具,所以只设置了一道管理员密码,没有用户的概念.但是很多同学在使用过后都提出了需要多用户支持的建议.整个团队或者整个公司都使用同一个密码来管理非常的 ...
- 【UG二次开发】装配设计
与装配相关的术语 tag 部件或对象的标识,还可能是部件原型.实例和事例 piece part 单个部件 occurrence 部件或对象的事例,装配中的是部件事例 object occurrence ...
- 不管卷不卷,面试还是得问问你G1原理!
所有的垃圾回收器的目的都是朝着减少STW的目的而前进,G1(Garbage First)回收器的出现颠覆了之前版本CMS.Parallel等垃圾回收器的分代收集方式,从2004年Sun发布第一篇关于G ...
- 三、JavaSE语言基础之数据类型
数据类型的分类 按照数据的复杂程度可分为引用数据类型与基本数据类型 引用数据类型的数据是对象(多值数据/复杂数据),引用数据类型的数据的名字叫做引用/引用名: 基本数据类型的数据是常量值( ...
- 二、JavaSE语言基础之常量与变量
1.常量 所谓常量值的是数据处理过程中值不能更改的数据. 2.变量 所谓变量值的是运算过程中值可以改变的数据,类似于代数中的未知数. 在Java语言中,使用变量时必须遵循先定义,而后赋值, ...
- 13.7Cloneable接口
要点提示:Cloneable接口给出了一个可克隆对象.
- 暑假自学java第二天
今天学习了一些java规则 一个java源文件的公开类只能有一个,而且必学和源文件名相同. 了解到java的标识符规范,这对以后的团队协作有很大作用. 标识符规则和c++还是很相似的 java中的字面 ...
- docker配置redis6.0.5集群
docker配置redis6.0集群方案 docker安装 请直接挂载课程配套的Centos7.x镜像, docker官方建议使用CentOS7 (1)yum 包更新到最新 sudo yum upda ...
- Tomcat:tomcat部署war包配置SSL访问
Linux-CentOS7部署 war放置 war放到tomcat的webapps目录内 修改配置 修改tomcat的server.xml文件 HTTP: 找到Connector元素,修改端口 HTT ...
- Java:Java的<<<移位运算符详解
1) 左移运算(<<) 左移就是把所有位向左移动几位 如: 12 << 2 意思就是12向左移动两位 12的二进制是: 0000 1100 通过这个图我们 ...