C++面向对象编程<六>:Big Three,三个特殊函数
来源:互联网 发布:精通shell编程 知乎 编辑:程序博客网 时间:2024/05/16 16:56
简介
这里看class的另一个分类:class with pointer members.
先看String的声明
#ifndef _MYSTRING_#define _MYSTRING_class String{ public: String(const char* cstr = 0); String(const String& str); //拷贝构造 String& operator = (const String& str); //拷贝赋值 ~String(); char* get_c_str const () {return m_data}; private: char* m_data; };#endif
如上所示:Big Three,三个特殊的函数:拷贝构造函数、拷贝赋值函数、析构函数。其实不写,编译器也会有默认的这些函数,那么什么时候需要写呢?就得看看编译器默认的这些函数够不够用。(默认的就是一个个位进行复制)
class with pointer members一般这样设计:指针作为成员变量,在需要内存的时候动态申请,而不是直接在class里放数组,因为不知道数组需要多大。显然得自己写Big three函数
class with pointer members 就一定要写构造函数、拷贝构造函数、析构函数
构造函数和析构函数
先看构造函数的实现
inline String::String(const char* cstr = 0){ if (cstr) { m_data = new char[strlen(cstr) + 1]; strcpy(m_data,cstr); } else //未指定值,形成空字符串 { m_data = new char[1]; *m_data = '\0'; }}
析构函数需要清理空间,这里的class有动态申请空间,若没有释放掉的话,会有内存泄露
inline String::~String(){ delete [] m_data;}
拷贝构造函数
如上String的设计,使用如下
String a("Hello");String b("World");b = a;
String类只包含m_data指针,并不包含其申请的动态空间,
如果使用默认拷贝构造函数,编译器会自己一个字节一个字节的复制,会出现的y严重的后果。如果把a的内容复制到b中去,就会出现a的m_data和b的m_data指向一个地方,那么b指向的内容”World”就没有指针指向他了,会出现内存泄露。而赋值后两个指针指向一块内存也很危险:你更改a,b就会受影响,所以这种叫浅拷贝,只会拷贝指针。会有两个隐患。(见下示意图)
改进方法就是使用深拷贝,如下
要去写的就是深拷贝。
先看拷贝构造函数,如下
String::String(const String& str){ m_data = new char[ strlen(str.m_data + 1) ]; strcpy(m_data,str.m_data);}
使用如下
String s1("Hello");String s2(s1); //以s1为蓝本、初值创建s2String s3 = s1; //调用拷贝构造函数 //把s1赋值到s3上,但s3也是新创建的对象(既然新创建的就要调用构造函数)。
拷贝赋值
使用如下
b = a;
首先明白:b和a对象都有内容,那么把b赋值给a,需要以下三个步骤
三步骤:先清空b的内容,再为b分配一个空间,然后再将a的内容拷贝过来给b。
下面看函数
inline String& String::operator = (const String& str){ if (this == &str) //检测自我赋值 return *this; delete[] m_data; m_data = new char[ strlen(str.m_data + 1)]; strcpy(m_data,str.m_data); return *this;}
注意:自我赋值检测的必要性,谁会做自我赋值的动作呢?所以说这样效率高,
如果没有写这两行,不仅仅是效率问题。如果没有这两行,可以试试赋值自己会出现什么bug。所以我自我赋值的检测是必要的
再看一个程序,看下什么时候调用 big three 函数
String str1("hello"); //调用构造函数String str2(str1); //调用拷贝构造函数String str3 = str1; //调用拷贝构造函数str3 = str2; //调用拷贝赋值函数
先给出String的完整程序
#ifndef __MYSTRING__#define __MYSTRING__class String{public: String(const char* cstr=0); String(const String& str); String& operator=(const String& str); ~String(); char* get_c_str() const { return m_data; }private: char* m_data;};#include <cstring>inlineString::String(const char* cstr){ if (cstr) { m_data = new char[strlen(cstr)+1]; strcpy(m_data, cstr); } else { m_data = new char[1]; *m_data = '\0'; }}inlineString::~String(){ delete[] m_data;}inlineString& String::operator=(const String& str){ if (this == &str) return *this; delete[] m_data; m_data = new char[ strlen(str.m_data) + 1 ]; strcpy(m_data, str.m_data); return *this;}inlineString::String(const String& str){ m_data = new char[ strlen(str.m_data) + 1 ]; strcpy(m_data, str.m_data);}#include <iostream>using namespace std;ostream& operator<<(ostream& os, const String& str){ os << str.get_c_str(); return os;}#endif
- C++面向对象编程<六>:Big Three,三个特殊函数
- C++面向对象编程<八>:小练习之Big three函数
- C语言面向对象编程(六):配置文件解析
- C语言面向对象编程之六:配置文件解析
- C++- Big Three in C99
- 面向对象编程中的三个重要机制
- 面向对象编程的三个基本特征
- 面向对象编程的三个基本特征
- 面向对象编程---函数
- 面向对象程序设计三个基本特征(C++)
- PHP面向对象编程 面向对象的特殊实践
- Python 面向对象 —— 特殊函数
- angular2系列教程(六)两种pipe:函数式编程与面向对象编程
- C++面向对象编程入门:构造函数与析构函数(六)
- 第八课 面向对象编程 (六)
- javascript面向对象编程(六)
- python学习笔记(六) - 面向对象编程
- C++面向对象编程(六) 继承
- How to install Mod_Security on Nginx
- iOS开发之 Objective-C语言基础 :代码块
- Linux命令学习手册-rsync命令
- 【菜鸟学Java】12:代理模式——静态代理怎么玩?
- LeetCode OJ - Remove Duplicates from Sorted Array
- C++面向对象编程<六>:Big Three,三个特殊函数
- 百思不得姐项目学习总结
- mysql 安装 原始密码修改
- HTML 将块设置成圆角
- Spring工作原理
- 碰到技术问题时,如何寻求帮助
- [2]Solr5.4.1配置DIH导入MSSQL数据
- 竞品分析报告正确的打开方式
- redis基本命令学习