欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

四、C++指针与引用

程序员文章站 2024-02-17 15:34:46
...

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指针运算

    1. 假设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指向指针的指针

  • 指向指针的指针是一种多级间接寻址的形式,当一个指向指针的指针时,第一个指针包含第二个指针的地址,第二个指针指向包含实际值的位置;
    四、C++指针与引用
#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引用和指针的区别

  1. 不存在空引用,引用必须连接到一块合法的内存;
  2. 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向另一个对象;
  3. 引用必须在创建的时初始化。指针可以在任何时候被初始化;

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

相关标签: C++学习总结