四、C++指针与引用
程序员文章站
2024-02-17 15:34:46
...
C++指针与引用
1.指针
- 每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字符(&)运算符访问的地址,他表示在内存终端地址:
#include <iostream>
using namespace std;
int main ()
{
int var1;
char var2[10];
cout << "var1 变量的地址: ";
cout << &var1 << endl;
cout << "var2 变量的地址: ";
cout << &var2 << endl;
return 0;
}
- 指针是一个变量,其值为另一个变量的地址,即内存位置的直接地址。
指针进行声明:
type *var-name;
int *ip; //声明一个整形指针;
char *ch;//声明一个字符性指针;
//不管时什么类型都代表内存地址的长的16位禁止;
- 指针使用实例:
#include <iostream>
using namespace std;
int main ()
{
int var = 20; // 实际变量的声明
int *ip; // 指针变量的声明
ip = &var; // 在指针变量中存储 var 的地址
cout << "Value of var variable: ";
cout << var << endl;
// 输出在指针变量中存储的地址
cout << "Address stored in ip variable: ";
cout << ip << endl;
// 访问指针中地址的值
cout << "Value of *ip variable: ";
cout << *ip << endl;
return 0;
}
//输出结果
/*
Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of *ip variable: 20
*/
1.1C++空指针
- NULL指针是一个定义在标注库中的值为零的常量;
int *ptr =NULL; 如果指针包含空值(0值),则假定它不指向任何东西
如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针。很多时候,未初始化的变量存在一些垃圾值,导致程序很难调试;
注意空指针不是指向地址为0的指针,地址为0的地址是留给系统的;
1.2指针运算
-
- 假设pre是一个指向地址1000的整形指针,是一个32位的整数;执行ptr++;ptr将执行位置为1004;增加了4个字节。这种运算会在不影响内存位置中的实际值的情况下,移动到下一个内存位置。
#include <iostream>
using namespace std;
const int MAX = 3; //const定义的变量,在程序中不允许修改
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// 指针中的数组地址
ptr = var;
for (int i = 0; i < MAX; i++)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// 移动到下一个位置
ptr++; //同理可以使用ptr--
}
return 0;
}
/*输出结果
Address of var[0] = 0xbfa088b0
Value of var[0] = 10
Address of var[1] = 0xbfa088b4
Value of var[1] = 100
Address of var[2] = 0xbfa088b8
Value of var[2] = 200
*/
- 指针可以使用关系运算符进行比较,如==、<和>;
- 由于一个数组名对应一个指针常量,只要不改变数组的值,仍然可以使用指针的形式的表达式
int var[2];
*var=i; //正确的语法
var++; //不正确
*(var+2)=500;//正确
``
## 1.3指针数组
- 定义一个指向整形指针数组的声明:
int *ptr[MAX];
ptr中每一个元素都是指向int值的指针;
```cpp
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr[MAX];
for (int i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; // 赋值为整数的地址
}
for (int i = 0; i < MAX; i++)
{
cout << "Value of var[" << i << "] = ";
cout << *ptr[i] << endl;
}
return 0;
}
/*
当上面的代码被编译和执行时,它会产生下列结果:
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
*/
顿悟:&是取普通常量或变量的地址,对于指针,它本身就存储的是常量或变量的地址,而非定义指针时的*,用来取指针所指地址里面存的值;
- 也可以使用指向字符的指针数组来存储一个字符串列表;
#include <iostream>
using namespace std;
const int MAX = 4;
int main ()
{
const char *names[MAX] = {
"Zara Ali",
"Hina Ali",
"Nuha Ali",
"Sara Ali",
};
for (int i = 0; i < MAX; i++)
{
cout << "Value of names[" << i << "] = ";
cout << names[i] << endl;
cout << &names[i]<<endl;
}
return 0;
}
/*
Value of names[0] = Zara Ali
0x7ffdd2e1c730
Value of names[1] = Hina Ali
0x7ffdd2e1c738
Value of names[2] = Nuha Ali
0x7ffdd2e1c740
Value of names[3] = Sara Ali
0x7ffdd2e1c748
*/
1.4指向指针的指针
- 指向指针的指针是一种多级间接寻址的形式,当一个指向指针的指针时,第一个指针包含第二个指针的地址,第二个指针指向包含实际值的位置;
#include <iostream>
using namespace std;
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
// 获取 var 的地址
ptr = &var;
// 使用运算符 & 获取 ptr 的地址
pptr = &ptr;
// 使用 pptr 获取值
cout << "var 值为 :" << var << endl;
cout << "*ptr 值为:" << *ptr << endl;
cout << "**pptr 值为:" << **pptr << endl;
return 0;
}
1.5传递指针给函数
#include <iostream>
#include <ctime>
using namespace std;
void getSeconds(unsigned long *par);
int main ()
{
unsigned long sec;
getSeconds( &sec );
// 输出实际值
cout << "Number of seconds :" << sec << endl;
return 0;
}
void getSeconds(unsigned long *par)
{
// 获取当前的秒数
*par = time( NULL );
return;
}
- 能接受指针作为参数的函数,也能结束数组作为参数:如下,
#include <iostream>
using namespace std;
//函数声明
double getAverage(int *arr, int size);
int main()
{
int balance[5]={100,23,23,123,232};
double avg;
//传递一个指向数组的指针作为参数
avg=getAverage(balance,5);
cout<<"Average value is :"<<avg<<endl;
return 0;
}
double getAverage(int *arr,int size)
{
int i,sum=0;
double avg;
for(i=0;i<size;++i)
{
sum+=arr[i];
}
avg=double(sum)/size;
return avg;
}
//输出:Average value is :100.2
1.6从函数中返回指针
- 声明一个从返回指针的函数:
int * myfunction()
{}
- 另外,C++不支持在函数返回局部变量的地址,除非局部变量为static变量;
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
// 要生成和返回随机数的函数
int * getRandom( )
{
static int r[10];
// 设置种子
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i)
{
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// 要调用上面定义函数的主函数
int main ()
{
// 一个指向整数的指针
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}
2.引用
- 引用是一个别名;即它是一个已存变量的另一个名字。
2.1引用和指针的区别
- 不存在空引用,引用必须连接到一块合法的内存;
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向另一个对象;
- 引用必须在创建的时初始化。指针可以在任何时候被初始化;
2.2C++中创建引用
- 可以这样理解,变量名称是变量附属在内存位置中的标签,那么引用就可以当做变量附属在内存位置中的第二个标签。
- 因此,可以通过原始变量名称或者引用来访问变量的内容;
int i= 12,d=12.23;
//可以为i声明引用变量;
int& r=i;
double$ s=d;
- 在上述声明中,&读作引用;第一个声明可以读作:r是一个初始化为i的整形引用;
#include <iostream>
using namespace std;
int main ()
{
// 声明简单的变量
int i;
double d;
// 声明引用变量
int& r = i;
double& s = d;
i = 5;
cout << "Value of i : " << i << endl;
cout << "Value of i reference : " << r << endl;
d = 11.7;
cout << "Value of d : " << d << endl;
cout << "Value of d reference : " << s << endl;
return 0;
}
2.3把引用作为参数
- C++支持把引用作为参数传递给函数,这比传一般参数更为安全;
#include <iostream>
using namespace std;
// 函数声明
void swap(int& x, int& y);
int main ()
{
// 局部变量声明
int a = 100;
int b = 200;
cout << "交换前,a 的值:" << a << endl;
cout << "交换前,b 的值:" << b << endl;
/* 调用函数来交换值 */
swap(a, b);
cout << "交换后,a 的值:" << a << endl;
cout << "交换后,b 的值:" << b << endl;
return 0;
}
// 函数定义
void swap(int& x, int& y) //x相当于a,和指针中传a的地址一样;
{
int temp;
temp = x; /* 保存地址 x 的值 */
x = y; /* 把 y 赋值给 x */
y = temp; /* 把 x 赋值给 y */
return;
}
//输出:
/*
交换前,a 的值: 100
交换前,b 的值: 200
交换后,a 的值: 200
交换后,b 的值: 100 */
2.4把引用作为返回值
- 通过使用引用来代替指针,会使C++程序更加容易阅读和维护。C++函数返回一个引用,方式与返回一个指针类似;
- 当函数返回一个引用时,则返回一个执行返回值的隐式指针,这样函数就可以放在赋值语句左边了;
#include <iostream>
using namespace std;
double vals[] = {12.23,132.2,12.4,6.8};
double& setValues(int i)
{
return vals[i]; //返回第i个元素的引用
}
int main()
{
cout<<"改变前的值"<<endl;
for(int i=0;i<5;i++)
{
cout<<"vals["<<i<<"]="<<vals[i]<<endl;
}
setValues(1)=20000.2; //改变第2个元素
setValues(3)=40000.2;//改变第4个元素
cout<<"改变后的值"<<endl;
for(int i=0;i<5;i++)
{
cout<<"vals["<<i<<"]="<<vals[i]<<endl;
}
return 0;
}
输出结果:
改变前的值
vals[0]=12.23
vals[1]=132.2
vals[2]=12.4
vals[3]=6.8
vals[4]=6.91923e-310
改变后的值
vals[0]=12.23
vals[1]=20000.2
vals[2]=12.4
vals[3]=40000.2
vals[4]=6.91923e-310
上一篇: Map 排序
下一篇: C语言学习笔记(四) --指针