Chapter 8

指针、引用
指针—— 存储内存地址
变量 ——占用空间、声明、初始化(否则值为随机)

8.1 运算符

1.1 使用引用运算符(&)获取变量地址

e.g. Varname —— 变量
&Varname —— 存储该变量内存地址

1.2 使用接触引用运算符(*)

以此访问包含地址的值
e.g. 有合法指针——pData
那么该指针地址处存储的值可用 *pData 来获取

1.3 sizeof()

用于指针时,结果取决于编译器及针对的操作系统,与指针变量无关。

8.2 动态内存分配

1. 关键字new & delete 动态分配和释放内存

new分配新的内存块,若成功,返回一个指针,指向新分配的内存,否则引发异常(使用时,指定数据类型分配内存)
Type* Pointer = new Type;
Type* Pointer = new Type[ Num Elements ];
e.g.

int * pNumber = new int;
int * pNumber = new int[ 10 ];

注 :请求分配内存并不保证请求能够得到满足,取决于系统状态机内存资源的可用性。
使用关键字 new 分配的内存最终使用对应的关键字 delete 释放
Type* Pointer = new Type;
delete Pointer;

Type* Pointer = new Type[ Num Elements ];
delete [] Pointer;

2. 递增(++)、递减(--)运算符作用于指针的结果

对指针执行递增 / 递减, 指向的是内存中相邻的值,而不是相邻的字节(除非值的长度刚好1字节,例如char)
Type * pType = Address;
++pType --> Adress + sizeof( Type )

3. 关键字const作用于指针

const指针有三种:
a )指针直线的数据为常量,不可修改,但可以修改包含的地址(指针可指向其他地址)
b ) 指针包含地址为常量,不能修改,可以修改数据
c ) 最为严格的情况,地址及值均为常量,均不可修改,但更易于维护。

4. 将指针传递给函数

将内存空间传递给函数,其中可包含值,可包含结果
注意传入的数据是否需要修改或者经过计算。

5. 数组与指针

可以将数组变量赋值给类型相同的指针。

8.3 常见错误

1.内存泄露

常见原因是未正确释放内存

2.指向无效的内存单元

无效指针

3.悬浮指针

亦可称之为迷途/失控指针
为便面此类问题,初始化/释放指针后将其置为NULL,并在解除引用前(使用关键字 ** * **)检查其是否有效。

8.4 编程实践

Step1 初始化指针变量
step2 使用前判断指针是否为NULL——>异常处理,在new(创建指针)失败时妥善退出
Step3 仅在其有效时使用
Step4 new之后必用关键字delete释放内存,且delete后不再访问该指针

8.5 引用(&)

引用是变量的别名(相应变量的的另一个名字,指向相同的内存单元)

VarType Original = Value;
VarType & ReferenceVariable = Original;

1.引用的用处

避免了传参时因参数占用内存过大,复制时也会开销很大。

2. const 用于引用

禁止通过引用修改其指向的变量的值。

const引用参数不能作用于左值

3. 按引用向函数传递参数

可避免将形参复制给形参,从而极大提高性能。然而,让被调用的函数直接使用调用函数栈时,确保被调用函数不能修改调用函数中的变量很重要。因此,可将引用声明为const

Chapter 9 类和对象

9.1 类和对象简述

1. 类的声明

关键字 class 依次包含类名、成员属性、方法(属于类成员的函数)及结尾分号(;
即通过关键字class创建数据类型,并封装属性。

"封装" 将数据及使用它们的方法进行逻辑编组

2.实例化对象

在使用时,根据类实例化一个对象,通过对象访问成员方法及属性。

class Human
{
    string Name;
    string DateofBirth;

    void Talk( string TexttoTalk );
};

那么实例化一个对象Tom

//方法一
Human Tom;

//方法二
Human* pAnotherHuman = new Human( );
delete pAnotherHuman;

3.通过句点运算符(.)访问成员

句点运算符(.)用于访问对象的属性。这同样适用于方法。


Human Tom;

Tom. DateofBirth = "1970" ;

Huamn* pTom = new Human();
(*pTom).IntroduceSelf();//使用间接运算符(*)获取对象,再使用句点运算符来访问成员。

4. 使用指针运算符访问成员(->)

若对象使用new实例化或有指向对象的指针,则可以使用 **指针运算符(->)**来访问成员属性和方法。

Chapter 11

**

11.1. 多态基础

1.1

类之间存在层次结构,类是通过继承相关联时,通过多态来表示。
多态意味着调用成员函数时,根据函数的对象类型执行不同的方法。(而不是调用预设的基类中的函数方法),即表现实际类型。

1.2

使用虚函数实现多态行为

将基类中方法声明为虚函数,使用关键字 virtual, 确保编译器调用覆盖版本(子类、派生类)。

多态行为 将派生类对象视为几类对象,并执行派生类的函数(方法)实现。

1.3 为何需要虚构造函数

除了需要使用派生类对象,还需要避免计算机资源未释放、内存泄露等问题(即将实例化的派生类对象,将其值赋给基类当做指针,并通过该指针调用 delete, 将不会调用派生类的析构函数)

												**⬇**

那么将析构函数声明为虚函数,确保通过基类指针调用delete时,不会调用派生类析构函数

class Base
{
public:
	virtual ~Base()		
};

auto 关键字

利用auto关键字,通过编译器检查变量的初始值,并将该变量类型设置为该返回值的类型。能够简化编码工作。

std::vector<int> MyNumbers;
	//常规
	for (vector<int>::const_iterator Iterator =  MyNumbers.begin(); 
		Iterator < MyNumbers.end(); ++Iterator )
	std::cout << * Iterator<< " ";
	//利用auto关键字
		for (auto Iterator =  MyNumbers.begin(); 
		Iterator < MyNumbers.end(); ++Iterator )
	std::cout << * Iterator<< " ";

**