【博览网】面向对象高级编程(上)——第二周课程笔记

来源:互联网 发布:大数据 技术体系 编辑:程序博客网 时间:2024/05/19 19:33

第二周的内容以带指针的类的设计为引子,讲解C++与内存相关的基本知识。涉及到内存的分配与操作、内存使用结构、堆和栈等知识。

一、带指针的类String
带指针的类是指在类中使用指针指向一片内存区域来存放类中的数据。这种方法实现的类在数据大小上有比较大的灵活度,但是在一些操作函数上则需要进行特殊的实现,以防止内存泄漏现象的发生。主要是拷贝构造函数、赋值函数和析构函数这三个函数。
以下代码均以String为例书写
1.构造函数与析构函数函数
构造函数需要使用new新申请一片内存来存放传入的数据,防止外部指针更改对象内部的数据。析构函数在对象被销毁时调用,需要使用delete释放对象申请的内存空间,否则对象被销毁时指针同时也被销毁,指针所指向的内存空间便会被泄漏。
2.拷贝构造函数与拷贝赋值函数
如果缺少这两个函数,编译器会自动生成默认的函数替代。编译器的默认函数执行的是按值复制,即只是将指针的值复制。而内存对象本身并未拷贝,因此会产生很多难以预计的错误。因此,我们需要自己手动书写拷贝构造函数和拷贝赋值函数,以实现指针所指内存的拷贝。

inline String::Sting (const String& str){    m_data = new char[strlen(str.m_data) + 1];    strcpy(m_data, str.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;}

二、堆、栈与内存管理
栈:存在于某作用域的一块内存空间
堆:由操作系统提供的一块global内存空间,程序可动态分配
二者的主要区别在于,栈空间的对象在离开作用域后会自动释放,但是堆空间的对象不会。

Complex c1(1, 2);     //c1所占用的空间来自栈Complex *p = new Complex(3);  //p所指向的对象所占用的空间来自堆

new操作符执行以下三个工作
• 分配内存到void指针上
• 将void指针转换为对象指针
• 调用构造函数构造对象
delete操作符执行以下两个工作
• 调用析构函数回收对象
• 将对象内存释放

在C++中,数组是以元素个数+元素的方式存储的,因此,在调用new[]和delete[]时,便会根据数组个数调用对应次数的构造和析构函数,如果对数组空间使用delete来析构,那么只会调用一次析构函数,可能会产生内存泄漏。

三、补充知识点
1.字节对齐
由于内存芯片的构造上的原因,计算机按照一定倍数读写内存速度是最快的(通常是4字节或者8字节,以4字节为例,读取0010、0011、0012、0013比读取0012、0013、0014、0016要快),因此需要将计算机中内存不足该倍数的部分补足该倍数,以提高计算机运算速度。
2.static关键字
使用static关键字修饰的变量被称为静态变量,在C语言中对这个概念已经有所接触,函数中的静态变量的特征就不在叙述。在类中声明的静态变量,是类所拥有的变量,类的所有对象都只拥有一份该变量的拷贝,该变量在堆中存储。
使用static修饰的成员函数是静态函数,在调用静态函数时,不会往函数中传入对象的this指针,因而静态函数只能使用类的静态变量,而不能使用对象中的数据。静态函数既可以通过对象来调用,也可以直接通过类来调用。
3.模版
模版是一种代码复用的手段,分为类模版和函数模版两种。其基本形式如下所示:

template <typename T>class Complex{private:    T re, im;public:}Complex<double> c1;Complex<int> c2;template <class T>inline T& min(const T& a, const T& b){    return b<a?b:a;}Stone r1(2,3),r2(3,3),r3;r3 = min(r1, r2);

与java不同,C++在调用模版函数时,会自动生成对应类型的源代码,因此会产生代码膨胀现象。

4.namespace命名空间
命名空间是一种防止类或函数重名的方法,便于在开发大型项目时进行代码管理。其基本使用格式如下:

namespace std{    ………}using namespace std;using std::cout;
阅读全文
0 0
原创粉丝点击