拷贝函数C++标准库复数类string解析(观看侯捷老师视频总结)
2018-03-20 11:37
267 查看
说在开始
观看了侯捷老师有关于拷贝构造和拷贝赋值的方法,其中涉及到浅拷贝,深拷贝等问题,当然在看本节部分的时候可能会产生很多的问题,我也是如此,产生问题的原因是因为对C/C++的内存管理机制掌握不好,当掌握了C/C++内存管理的机制后这些问题就会迎刃而解了。我也会写一篇关于C/C++内存管理机制的博客的。在这里进行总结,本节的代码都可以在我的github上找到https://github.com/ModestBean/C-Samples。本节解析了C++标准库当中的string类,自己用代码实现了,当然这里是阉割版,因为C++标准库当中的string功能实在是太复杂了,这里实现了几个简单的string的构造函数,拷贝函数等。
我们应当时刻注意一点:当我们设计的类当中有指针的时候,一定要时刻注意内存泄露,野内存等问题,也就是当类中有指针的时候,我们应该时刻注意。
如果自己的类当中含有指针,不可以使用编译器默认的拷贝函数,接下来我将会解释为什么不可以使用默认器的拷贝函数。
代码部分
先给出代码,看一下整个string类的基本架构吧,然后才好理解下面的概念问题,同样,侯捷老师把函数的实现代码放到了头文件当中,当然他使用了inline,大家需要注意.h文件用来声明是不进行编译的。String.h
#ifndef _MY_STRING #define _MY_STRING class String { public: String(const char * cstr=0);//满足 String s1("hellow")的构造方式 String(const String& str);//满足 String s1(s2)的构造方式 String& operator = (const String& str);//满足 s1=s2的方式 ~String(); private: char * m_data;//自己的数据数组 }; #include <cstring> inline String::String(const char * cstr)//构造函数,满足 String s1("hellow")的构造方式 { if (cstr) {//判断是不是0 m_data = new char[strlen(cstr) + 1]; strcpy(m_data, cstr); }else { m_data = new char[1]; *m_data = '\0'; } } inline String::String(const String& str)//构造函数,满足 String s1(s2)的构造方式 { m_data = new char[strlen(str.m_data) + 1]; strcpy(m_data, str.m_data); } inline String::~String()//析构函数 { delete[] m_data; } 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; } #endif //_MY_STRING
main.cpp
#include <iostream> #include "String.h" using namespace std; int main() { String s1("hello"); //第一种构造方式 String s2("world"); String s3(s2);//第二种构造方式 /* 两种构造方式: 1、此时的s1是不存在的,直接将hello给s1 2、第二种方式,s2和s3都是存在的,将s2的内容传递给s3 */ s3 = s1;//把s1的值拷贝给s3,这里重载了操作符“=”,所以才可以完成,否则出现浅拷贝问题,稍后解释,继续往下看。 cin.get(); return 0; }
几个概念
浅拷贝
如果自己使用系统的拷贝函数。也就是直接赋值=。会出现以下的错误结果:浅拷贝从图中可以看到有两个String 对象 a和b ,其中a当中的data指针指向的是“Hello”,b的data指针指向的是“Wordld”。当使用系统的a=b时,会出现图片下半部分的错误。也就是a和b两个对象中的指针会同时指向“Hello”
这样会带来两个问题:
1、造成内存泄露,两个data指针同时指向一个区域,“world”区域没有进行释放。
2、a,b两个对象中的data指针同时指向一个区域,操作可能会出现错误。
深拷贝
这里使用了C原来的拷贝函数,首先动态分配了一块内存,然后将另一个字符串中的内容拷贝到新分配的内存中 。我使
4000
用VS2015使用这段代码的时候会提示该方法可能会出现安全性错误,建议使用strcpy_s,但是使用C-Free这种轻量行的编译器就不会出现这种错误。我的猜想有以下两点
1、C-Free比较轻量,VS适用于大型项目的开发,比较严谨。
2、C-Free更加倾向于C语言,对于C++语言的完善的可能不是很好。
拷贝赋值函数
可以看出,此块代码是重载了操作符“=”也就是s1=s2所做的事情,这个方法也是比较重要的方法。其大致可以分为两大部分。
1、首先释放this指针指向的内容,然后分配一块与str指向的大小相同的内存区域,然后在进行深拷贝。
2、其中还有检测自我赋值的内容,这里应该时刻注意。如果检测到是自己赋值给自己,那么什么都不要做,直接返回,效率更高
3、如果不写自我检测可能会出现的错误结果:
去掉自我检测部分的代码,一步步分析:
前提,两个指针都是指向的Hello,当执行第一句代码
delete[] m_data;后,两个指针指向的都是空内容,此时
m_data = new char[ strlen(str.m_data) + 1 ];就无法处理。应该时刻注意。
最后
如果觉得文字内容不好理解的话,大家可以想看视频资源的话,可以 VX qq619192323。有什么错误还希望大家指出,一起共同进步。MBean
相关文章推荐
- C++标准库复数类complex解析(观看侯捷老师视频总结)
- 内存管理、堆、栈(观看侯捷老师视频总结)
- Linux学习笔记(观看韩顺平老师Linux视频的总结)
- 观看小辉老师mysql视频总结文档
- 记 Linux 学习知识总结 -- 寒江老师视频(六) - 文件的统计与文件的压缩
- 记 Linux 学习知识总结 -- 寒江老师视频(七) - SHELL 讲解
- 看陈广老师c#参考视频总结(第一篇)
- css应用给网页的4种方式(看张鹏老师的视频课程后所总结的)
- 传智播客java培训2010年4月18java高新技术3,张孝祥老师视频自学总结
- html超级链接(看张鹏老师的视频课程后所总结的)
- 陈广老师C#参考视频 方法的参数传递 总结
- css基本语法结构(看张鹏老师的视频课程后所总结的)
- 看陈广老师c#参考视频总结(第二篇)
- 看陈广老师c#参考视频总结(第五篇)
- 看陈广老师c#参考视频总结(第三篇)
- 看陈广老师c#参考视频总结(第六篇)
- 黑马程序员——看完毕老师的多线程视频,多线程的小总结
- 看陈广老师c#参考视频总结(第四篇)
- 看陈广老师c#参考视频总结(第七篇)
- 看陈广老师c#参考视频总结(第八篇)