一、指针
指针:增加程序弹性的同时,也增加了操作复杂度。
1. 形式
//定义时必须在类型名称之后加上*号
type *name
2. 含义
- 指针代表某特定类型对象的内存地址;
- 指针不直接操作对象;
- 指针为程序引入一层间接性。
3. 取址
取址运算符:&
int *pi=&ival; //将pi的初值设置为ival所在的内存地址,或者说pi指针指向了对象ival
4. 提领
要访问一个由指针所指的对象,则必须对该指针执行提领(dereference,也可称解除引用)操作,即:取得“位于该指针所指内存地址上”的对象。
在指针前使用 *
*pi=1024; //把数值1024写到pi指针所指的对象ival中,即:使得ival=1024
注意:指针可能并不指向任何对象!
如果pi不指向任何对象,则提领pi会导致未知的执行结果。
5. 成员选择运算符
- dot成员选择运算符(即:“.”),用来选择我们想要进行的操作;
//eg.
fibonacci.empty();
-
arrow成员选择运算符
若要通过指针来选择操作,必须改用arrow成员选择运算符;
!pv->empty();
//由于指针可能未指向任何对象,所以在调用empty()之前,应该先检验pv是否为非零值
if(pv&&pv->empty())
...
- 如果要使用下标运算符,则必须先提领pv。
//下标运算符的优先级较高,因此pv提领操作的两旁必须加上小括号
if ( pv && !pv -> empty() && ((*pv)[1] == 1 } } //[]是下标运算符
6. 初始化
- 一个未指向任何对象的指针,其地址值为0,也就是该指针是null指针;
- 任何指针都可以被初始化,或是令其值为0。
//eg.
int *pi=0;
double *pd=0;
string *ps=0;
7. 检验指针是否为0或null
//eg1.
if(pi&&*pi!=1024)//若pi=0(null指针),则if包含的语句不会执行
*pi=1024;
//eg2.
if(!pi)//当pi值为0时,条件表达式为true
8. 实例
以下六个vector对象(代表六个数列),我们需要一个指针,指向一个元素类型为int的vector:
vector<int> fibonacci, lucas, pell, triangular, square, pentagonal;
8.1. 方式一
//指针指向vector<int>,因此我们把它命名为pv,并给定初值0
//pv可以依次指向每一个表示数列的vector
vector<int> *pv=0;
//或者
//将数列的内存地址赋值给pv
pv=&fibonacci;
//...
pv=&lucas;
该方式会牺牲程序的透明性。
8.2. 方式二
const ine seq_cnt=6; //一个指针数组,大小为seq_cnt
vector<int> *seq_addrs[ seq_cnt ] = {
&fibonacci, &lucas, &pell,
&triangular, &square, &pentagonal
}; //每个指针都指向vector<int>对象
//seq_addrs是个array,其元素类型为vector<int>*
//seq_addrs[0]所持有的值是fibonacci vector的地址
//seq_addrs[1]的值是lucas vector的地址,以此内推
//我们通过一个索引值而非其名称来访问各个vector
vector<int> *current_vec = 0;
//....
for (int ix = 0; ix < seq_cnt; ++ix )
{
current_vec = seq_addrs[ix]; //所有要显示的元素都通过current_vec间接访问
}
该方式将每个数列的内存地址存入某个vector中,通过索引的方式,透明地访问这些数列。
二、伪随机数生成器
rand()和srand()都是C语言标准库中的函数,即C语言标准库提供的所谓伪随机数生成器。
- 在程序中出现这两个函数(或其一)时,必须在程序开头包含
#include<cstdlib>
; - srand()的参数:随机数生成器种子(seed);
- 使用同种子、相同数调用 rand()会导致相同的随机数(伪随机数)序列生成;
- 每次调用rand(),都会返回一个介于0和“int所能表示的最大整数”间的一个整数,可根据需要调整这个范围。
#include <cstdlib>
srand(seq_cnt);//设置rand()的随机数种子
seq_index = rand() % seq_cnt;
current_vec=seq_addrs[seq_index];