四、C++指针与引用

孤者浪人 提交于 2020-03-12 11:35: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指向指针的指针

  • 指向指针的指针是一种多级间接寻址的形式,当一个指向指针的指针时,第一个指针包含第二个指针的地址,第二个指针指向包含实际值的位置;
    在这里插入图片描述
#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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!