1 本章将主要介绍关于底层的技巧--内存管理和低级数据结构
2 使用数组和指针,可以控制内存分配,但是使用链表和向量等库函数,不可以控制内存的分配
3 数组是一种容器,指针是一种随机存取的迭代器,两者相辅相成
4 指针:存放对象的地址 &取地址运算符 *间接引用算符
指针变量赋值前没有意义,初始化为0,即空指针(0是
唯一一个可以被转化为指针类型的整型值)
指针也有类型,指向什么类型就是什么类型指针
1 指向对象的指针
声明:int *p; (int* p 也对,但是容易出现误解)
初始化 int *p=&a;
注意*p和a是完全等效的
2 指向函数的指针(对于函数来说,只有调用和获取地址两种操作)
函数不是对象,不可以复制和赋值,无法直接作为参数
在第六章的调用实际上使用了指向函数的指针进行操作
任何时候出现函数名,不是调用,即使没有&也是取地址操作
声明:int (*fp) ( int ); 间接调用函数指针fp int类型的返回值和参数
定义:fp=&next; 等价于fp=next;
使用:i=(*fp)(i); 或者 i=fp(i);
函数analysis作为参数时,以上两种写法都可以
想写一个以指针为返回值的函数,需要先typedef 指针
typedef double (*analysis_fp) (const int&);
tanalysis_fp get_analysis_ptr();
在函数指针作为参数、&和*都可以省略这两个符号,默认相同
5数组:容器,语言核心,不属于标准库。
内部有至少一个同类型元素,且在编译时大小确定,不能像向量等动态改变大小
只有类才有成员函数、成员变量,数组不是类,所以没有。
成员函数 .size() 成员变量size_type 无符号类型
数组的大小类型 size_t 在 <cstddef>t头中
sizeof()函数用来获取数组的元素占用多少内存,以字节为单位
想要知道数组的个数,则再除以一个元素所占内存,*/sizeof(*numbers)这里nvmbers是首地址
声明 : double cords[3];
const size_t NDim=3 ; double cords[NDim];
数组初始化:
6 数组和指针的关系:
数组名默认是指向数组首元素的指针,可以*cords 间接引用
例如*cords=1.5;
指针为0 指向第一个元素,指针可以加减n,以随机访问,
cords+3 超出地址,但是有效,只是不可预测。
Ptrddif标示两个指针相加减的类型,有符号,在<cstddef>头
指针a+i只有在0<=i<=n时才有效,n为数组大小
指针支持索引功能,指针p,p[n]指第n+m元素,不是地址
7 字符串常量:字符串常量数组,大小为个数加一,最后是’\0’,是终止符
数组只给第一个地址,直到第一个空白符停止
<cstring>头中strlen用来求数组和字符串常量大小的函数,不包括终止符。 string s(hello);等价
string s(hello,hello+strlen(hello));
都是hello(p185定义的)的复制
8 向main主函数的参数:1 整形参数 argc
2 指向字符首地址的指针参数 agrv
argv是一个指向一个指针数组首元素 的指针
argc是指向数组中指针的个数
argv的首元素总是指向mian函数编译后的程序名,因此argc至少为1
例子:将一个主函数编译成程序,命名say
say hello world
argc=3
argv为say、hello、world三个字符常量的首地址
9 标准错误流,用来进行异常输出,关键词cerr、clog,结果一样,在处理缓冲有点差别。clog生成日志,同cout缓冲特性,平时存储,适当时候输出
cerr即时输出,出错就报
10 c++标准库中用于文件输入输出和异常输入输出的对象类型不同
ifstream/ofstream
在处理文件,定义ifstream/ofstream时需要定义一个string类型文件名,即指向空字符结尾的字符数组作为文件名参数
例如: ifshtream infile(“in”);等价于
ifshtream infile(file.c_str()); 其中infile是一个string型变量,c_str是成员函数
11 三种内存分配方法:
1) 自动分配法:常与局域变量联系到一起,定义时自动分配,定义模块
结束则释放内存,释放后其指针失效,c++不报错!!
2) 静态分配: 静态变量可以解决问题,static有一个问题,就是无论怎么变化,指针被声明static就不再变化,原本指向一个函数的指针会随着每次调用重新定义。
3) 动态分配:
a给对象分配
new T 即为类型T 分配内存,构造函数初始化,产生一个新内存对象的指针。
int *p=new int(42);
new会给变量赋予一个特定值,如int型的42
p是指向对象的指针
delete p删除p,delete只能删除new产生指针。
也可以 int *p()
{
return new int(42);
}
b 给数组分配
new T[n] 为一个n个T类型对象的数组分配内存(数组包含n个T)
并返回指向首地址的指针。
初始化:
除了内部类型+局部作用域,不初始化,其他情况都会默认初始化。
类T:内部元素缺省构函数进行初始化
自定义类型T:1 T不允许默认初始化,则编译器将终止程序
2 n个元素都会初始化,比较耗时,标准库有更好的方法。
12 一个数组至少一个元素,若 new T[0],则无元素,返回的指针为有效的无意义off-the-end指针。数组释放内存 delete[]p;对数组分配内存,只有在程序结束或者delete,
13 注意*是间接引用,也是指针的一种表现
int *p=nums+100;nums是一个大小为100的数组;这里p是一个指向nums最后一个元素后面的指针。
14 argc argv是main的参数,主要是录入命令行,由于这里的命令行在编译之后运行之前输入,因此只能在terminal中输入,IDE不可以,**argv和*argv[]都可以,char *a=”hello”; 这里a是指向h的指针,*a 为h
15 ofstream和ifstream都是文件的输入输出对象,也是在terminal中才有效。
16友元:friend,用于自定义类中,介于public、private之间,friend可以让普通函数对被保护的元素访问,又不必设置成public。