指针
1. 对指针进行递增和递减
在程序中,我们有时会对指针进行“++”、“–”操作,这时需要注意的是对指针的递增或递减操作的结果是指针指向了内存块中的相邻的值(并不是加减1个字节),编译器自动认为内存中相邻的值也是本类型的。例如当前指针类型为int,则对指针进行加1后,指针的数值增加4字节(sizeof(int)),指向下一个int数值。
#include <iostream>
using namespace std;
int main()
{
int count = 3; // 输入数字个数
int* point = new int[count];
for(int i = 0; i < count; i++)
{
cout << "enter your " << i << " num:";
cin >> *(point + i); // 指针递增
}
// display
cout << "output: ";
for(int i = 0; i < count; i++)
{
cout << *(point++) << " ";
}
cout << endl;
delete [] point;
return 0;
}
输出:
enter your 0 num:1
enter your 1 num:2
enter your 2 num:3
output: 1 2 3
2. 指针与const关键字
我们都知道const关键字修饰的变量不可再更改,但是const不仅能修饰一般变量也能修饰指针,但是由于指针的复杂性,const修饰指针可以简要分为以下三种情况:
1、 const修饰指针的数值,此时指针指向的地址不能变,即不能再指向其他地址:
int day = 31;
int* const pDay = &day;
*pDay = 1; // 允许
1、 const修饰指针本身,也即修饰指针指向的数值,该数值为常量,不能再改变;
int day = 31;
const int* pDay = &day;
*pDay = 1; // 错误!
int newDay = 29;
pDay = &newDay; // 允许
1、 const即修饰指针的数值也修饰指针本身,则两者都不能再改变。 将指针传递给函数时,这种形式很有用,两者都不能被修改,以确保函数不会修改指针。
3. 使用指针的注意项
1、 内存泄露:在使用new动态分配内存时一定要在结束时delete释放。
2、 指针指向无效的内存单元:因为指针不要求一定要初始化(引用要求初始化),所以指针无初始化可能会导致程序崩溃。
3、 检查使用new分配内存的请求是否成功。
引用
与指针不同,首先在声明引用时必须将其初始化为一个变量,后面不允许再引用其他变量。这也是引用的优点,使用指针作为形参时我们不能保证指针的数据的合法性,可能指向了越界或不存在的地址;但是引用声明时就必须初始化,不会无效。
1. 在哪里使用引用
当我们调用函数时:
// 1. 调用时引起拷贝
returnType MyFunc(type param);
returnType result = MyFunc(argument);
// 2. 调用时引用不需要复制
returnType MyFunc(type& param);
returnType result = MyFunc(argument);
如上所示,当调用函数“MyFunc”时,需要将变量argument复制到形参param中,如果argument数据量比较大时这个复制过程就会比较耗时。但是当使用引用时,argument是按引用传递,不需要耗时的拷贝过程。
2. 使用const修饰引用
我们知道引用一旦初始化后将无法指向其他内存地址,但是仍然可以通过引用来修改变量的值,但是有时我们需要禁止函数通过引用修改它所指向的变量的值时,就可以在声明引用时使用关键字const:
int num = 30;
const int& constRef = num;
constRef = 31; // 错误!不允许更改
int& normalRef = constRef; // 错误!normalRef不是const类型的