`
anson_xu
  • 浏览: 502060 次
  • 性别: Icon_minigender_1
  • 来自: 惠州
社区版块
存档分类

今天看了两个小时<<21天学通C++>>把C++中的指针、引用、传值问题弄清楚了

 
阅读更多

今天看了两个小时 <<21 天学通 C++>> C++ 中的指针、引用、传值问题弄清楚了

 

记住引用理解成别名

 

 

形参 出现在函数定义中,在整个函数体内都可以使用, 离开该函数则不能使用。 形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元

实参 出现在主调函数中,进入被调函数后,实参变量也不能使用。参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。

 

1.       指针

声明指针

// 声明一个空指针 p

int *p = 0;

 

int pTmp; = 50;

int *p = & pTmp; <==> int *p ;

                                    *p = & pTmp;

       其中 p 里面存放的是 pTmp 的地址,

              & 取地址符号

*p = & pTmp 只有在指针初始化时这样用,其实这种写法容易引起歧义;

              此时:

              p 中存放的是 pTmp 的地址;

              *p 指的是指存储在指针的内存地址中的值 也就是 pTmp 的值;

              &p 取指针本身的地址

              所以:

              cout<<*p // output : 50

cout<<p // output : 0x22ff56 pTmp 变量所在的地址值;

cout<<&pTmp // output : 0x22ff56 pTmp 变量所在的地址值;

cout<<&p // output : 0x32fe88 p 本身的地址值;

p 指向变量,对 p 重新赋值就会改变 p 所指向变量的值,同样对 p 指向的变量重新赋值也会改变 *p 的值。

注意:

如果是char数组或者int数组时

定义方法:

     char *p1 = "name"; <==> char s[ ] = "name"; char *p1; p1 = s;
printf("%s \n",p1 );//这里是 p1 output: name
printf("%c\n",*p1);//output: n

 

     int b[3] = {15,19,20};
int *i;                           <==> int *i = {15,19,20};
i = b;
printf("%d \n",*i );//这里是 *i output:15

 

ps:指针赋值问题

      char * p1 ="name";

      char *p2;

      p2 = p1 ;//正确

      while(*p2++ = *p1++) ;//错误

     因为p1++每执行一次,指针就会后移一位,到末尾时指向"\0",故执行完后p2 为NULL

指针控制循环问题

 

当为int型数组时 ,不能用指针来作为循环条件

int arr[20];

int *ptr = arr;

int i;

for(i=0;i<20;i++)

{

     ptr++; //指针加1

    (*ptr)++;//指针指向内容加1

}

 


当为char型数组时

char *p="abc";

while(*p)   // 当*p为‘/0’时终止

{

     printf("%d\n",*p);

    p++;

}


 

 

2.       引用

引用实际是其他变量的别名,对应用的操作就是对其引用的变量的操作

int pTmp1 = 20;

int pTmp2 = 22;

       int &p = pTmp1; // 初始化的方式

 

       引用重新赋值问题,会改变其引用的变量的值

       p = pTmp2;

       则:

       cout<< p // output : 22

       cout<< pTmp1 // output : 22

   

3 传参

 

 

i.              值传递:处理的是实参的拷贝,不会对实参产生影响。

 

代码 1

#include <iostream>

using namespace std;

void swap(int x,int y);

int main()

{

     int x = 5,y = 10;

     cout<<"main:before swap x = "<<x<<" y = "<<y<<"\n";//output: x=5,y=10

     swap(x,y);

     cout<<"main:after swap x = "<<x<<" y = "<<y<<"\n";//output: x=5,y=10

     //return 0;

}

 

void swap(int x,int y)

{

      int tmp;

      cout<<"swap:before swap x = "<<x<<" y = "<<y<<"\n"; //output: x=5,y=10

      tmp = x;

      x = y;

      y = tmp;

      cout<<"swap:after swap x = "<<x<<" y = "<<y<<"\n";//output: x=10,y=5

}

注意:#define swap(a,b) a=a+b;b=a-b;a=a-b; 这种形式就会影响实参

 

                 ii.              指针通过引用传参:

代码 2

#include <iostream>

using namespace std;

void swap(int *x,int *y);

int main()

{

     int x = 5,y = 10;

     cout<<"main:before swap x = "<<x<<" y = "<<y<<"\n";//output: x=5,y=10

     swap(&x,&y); // xy 的地址被做为参数传递给 swap

     cout<<"main:after swap x = "<<x<<" y = "<<y<<"\n";//output: x=10,y=5

     //return 0;

}

 

void swap(int *x,int *y ) // int *x = &x ,int *y = &y

{

      int tmp;

      cout<<"swap:before swap x = "<<*x<<" y = "<<*y<<"\n"; //output: x=5,y=10

      tmp = *x;

      *x = *y;

       *y = tmp;

      cout<<"swap:after swap x = "<<*x<<" y = "<<*y<<"\n";//output: x=10,y=5

}

 

                iii.              引用通过引用传参

 

代码 2

#include <iostream>

using namespace std;

void swap(int &x,int &y);

int main()

{

     int x = 5,y = 10;

     cout<<"main:before swap x = "<<x<<" y = "<<y<<"\n";//output: x=5,y=10

     swap(x,y); // 变量 x y 被做为参数传递给 swap

     cout<<"main:after swap x = "<<x<<" y = "<<y<<"\n";//output: x=10,y=5

     //return 0;

}

 

void swap(int &rx,int &ry ) // int &x = x ,int &y = y 这里 rx ry x

y 的别名

{

      int tmp;

      cout<<"swap:before swap x = "<<*rx<<" y = "<<*ry<<"\n"; //output: x=5,y=10

      tmp = rx;

      rx = ry;

      ry = tmp;

      cout<<"swap:after swap x = "<<rx<<" y = "<<ry<<"\n";//output: x=10,y=5

}

 

int & *p; //不能建立指向引用的指针;int *a; int * & p=a; //正确,指针变量的引用

 引用和指针使用原则:
1.在可以用引用的情况下,不要用指针;
2.引用不允许重新赋值.,当使用一个变量指向不同的对象时,必须用指针;
3.引用不允许为空,当存在对象为空时,必须使用指针。


引用说明:
(1) double & rr=1; 等价与 double temp; temp=double(1); double & rr=temp;
(2) int *a; int * & p=a; int b=8; p=&b; //正确,指针变量的引用
void & a=3; //不正确,没有变量或对象的类型是void
int & ri=NULL; //不正确,有空指针,无空引用
(3) int & ra=int; //不正确,不能用类型来初始化
int *p=new int; int & r=*p; //正确
(4) 引用不同于一般变量,下面类型声明是非法的:
int &b[3]; //不能建立引用数组
int & *p; //不能建立指向引用的指针
int &&r; //不能建立引用的引用
(5) 当使用&运算符取一个引用的地址时,其值为所引用变量的地址,

 

一段代码:

1  #include  < iostream >
 2  
 3  using   namespace  std;
 4  
 5  void  freePtr1( int *  p1)
 6  
 7  {
 8  
 9     delete p1;
10  
11     p1  =  NULL;
12  
13  }
14  
15  void  freePtr2( int *&  p2)
16  
17  {
18  
19     delete p2;
20  
21     p2  =  NULL;
22  
23  }
24  
25   
26  
27  void  main()
28  
29  {
30  
31      int   * p1  =   new   int ;
32  
33      * p1  =   1 ;
34  
35     freePtr1(p1);
36  
37      int   * p2  =   new   int ;
38  
39      * p2  =   2 ;
40  
41     freePtr2(p2);
42  
43     system( " pause " );
44  
45  }

思考:在freePtr1和freePtr2 的比较中,你能发现它们的不同点吗?

 

二、对代码进行解释:

#include <iostream>

using namespace std;

void freePtr1(int* p1)

{

   //未释放内存前 ->  p1 Address : 0012FDDC  p1 value : 003429B8,在这里,p1它也是一个变量,既然是一个变量,那么它将会以值的传递,把外部变量p1传到栈内,在栈内产生一个地 址:0012FDDC,当然,它的值不会变仍然是指向堆地址:003429B8 。

   delete p1; //系统回收p1值的地址003429B8处的内存。

p1 = NULL;//对p1赋以NULL值即:00000000,注意:p1本身的地址并没有变,变的是p1的值。

   //释放内存后 ->  p1 Address : 0012FDDC  p1 value : 00000000,出栈后,p1由于是一个临时对象,出栈后它会自动被视为无效。

}

void freePtr2(int*& p2)

{

   //未释放内存前 ->  p2 Address : 0012FEC8  p2 value : 003429B8,p2是一个指针的引用,即引用指向指针,记住引用的特点:对引用的对象直接操作。所以它的地址和值与栈外的main()函数中,p2的 值是同一个。

   delete p2; //对p2所引用的指针进行释放内存,即:系统回收main()函数中 p2的值 003429B8 地址处的内存。

   p2 = NULL;//对main()函数中p2的指针赋以NULL值。

   //释放内存后 ->  p2 Address : 0012FEC8  p2 value : 00000000,由于操作的对象都是main()函数中的p2,所以它将应用到原变量中。

}

 

void main()

{

   int *p1 = new int;

//释放内存前->  p1 Address : 0012FED4  p1 value : 003429B8

   freePtr1(p1);

   //释放内存后->  p1 Address : 0012FED4  p1 value : 003429B8

 

   int *p2 = new int;

   //释放内存前->  p2 Address : 0012FEC8  p2 value : 003429B8

   freePtr2(p2);

   //释放内存后->  p2 Address : 0012FEC8  p2 value : 00000000

   system("pause");

}
-----------------------------------------------
指针引用的经典用法:

#include <iostream>
using namespace std;


void all1(int **p)
{
 int *pp = new int;
 *p = pp;
}
void all2(int*& p)
{
 int *pp = new int;
 p = pp;
}

void main()
{
 int *a1;
 all1(&a1);
 *a1 = 1;
 cout<<*a1<<endl;

 int *a2;
 all2(a2);
 *a2 = 2;
 cout<<*a2<<endl;

}

分享到:
评论

相关推荐

    21天学通Visual C++(第2版)

    《21天学通C++(第2版)》站在...《21天学通C++(第2版)》适合没有编程基础的C++语言初学者作为入门教程,也可作为大、中院校师生和培训班的教材,对于C++语言开发的爱好者,《21天学通C++(第2版)》也有较大的参考价值。

    21天学通C++(第五版) vs2008程序打包 深入浅出MFC 浙大教材C++达内 C++ 华为C++培训资料 visual c++_MFC

    21天学通C++(第五版) vs2008程序打包 深入浅出MFC 浙大教材C++达内 C++ 华为C++培训资料 visual c++_MFC 资源内容: visual c++_MFC 达内 C++ C++课件.ppt c++源码 .rar Core C++ Programming_new.ppt Core C++ ...

    21天学通C++习题答案

    21天学通C++习题答案21天学通C++习题答案21天学通C++习题答案21天学通C++习题答案21天学通C++习题答案

    21天学通c++ 一本不错的学习教程

    本书是C++语言的入门教程,较为系统地介绍了C++语言的基础内容。本书包括6篇共21章的内容。其中,第一篇是C++数据表达篇,主要内容包括:C++入门、变量和数据类型、运算符和表达式以及程序控制结构等;第二篇是C++...

    21天学通 C++(第8版)完整高清

    21天学通 C++(第8版)完整高清 已统一页面大小和重新制作书签,出版日期:2017.09。

    赋值传值,引用传值,指针传值的区别

    构造函数,借助构造函数 解释 【赋值传值】,【引用传值】,【指针传值】

    21天学通C++第七版完整版PDF下载

    21天学通C++第七版完整版PDF下载,这个pdf有170多兆,是完整版的,500页左右,我只能上传60M以下的文件,所以给的是百度网盘地址及密码,永久有效

    21天学通C++(第四版)

    21天学通C++(第四版)21天学通C++(第四版)21天学通C++(第四版)21天学通C++(第四版)21天学通C++(第四版)21天学通C++(第四版)21天学通C++(第四版)21天学通C++(第四版)21天学通C++(第四版)21天学通C++...

    C++语言的入门教程---21天学通C++

    《21天学通C++》是C++语言的入门教程,较为系统地介绍了C++语言的基础内容。《21天学通C++》包括6篇共21章的内容。其中,第一篇是C++数据表达篇,主要内容包括:C++入门、变量和数据类型、运算符和表达式以及程序...

    21天学通c++

    《21天学通c++》c++学习者的入门基础资料

    21天学通C++:第4版

    21天学通C++:第4版

    21天学通C++ 第2版

    21天学通C++ 第2版 出版社: 电子工业出版社; 第2版 (2011年2月1日) 丛书名: 21天学编程系列 平装: 418页 正文语种: 简体中文 《21天学通C++(第2版)》站在初学者的角度,较全面地介绍了C++的相关知识,较为系统...

    21天学通+C++第8版+高清完整带书签PDF+源码

    21天学通c++高清完整带书签PDF源码,本书简单易懂,实例很容易被调试和理解,是一本c++入门的经典教材。

    21天学通C++第8版 高清完整PDF.pdf

    被名字误导了的一本好教材。

    21天学通c++

    在初学者的角度,较全面地介绍了c++的相关知识,较为系统地介绍了c++语言的基础内容。本书包括6篇共21章的内容。其中,第1篇是c++数据表达篇,包括c++入门、变量和数据类型、运算符和表达式以及程序控制结构等;第2...

    C /C++库函数及文件大全 经典 chm

    Character &lt;br&gt;Standard C Math &lt;br&gt;Standard C Time & Date &lt;br&gt;Standard C Memory &lt;br&gt;Other standard C functions &lt;br&gt;All C Functions&lt;br&gt;C++&lt;br&gt;C++ I/O &lt;br&gt;C++ Strings &lt;br&gt;C++ String Streams &lt;br&gt;...

    java及C++中传值传递、引用传递和指针方式的理解.docx

    java及C++中传值传递、引用传递和指针方式的理解.docx

    《21天学通C++ (第6版)》第六版[PDF]

    只需每天一小时便可具备开始使用C++进行编程所需的全部技能。通过阅读这本内容全面的教程,读者可快速掌握基本知识并学习更高级的特性和概念: 掌握有关C++和面向对象编程的基本知识; 学习一些C++高级特性; 学习...

    21天学通C++(高清中文第6版)

    作者:Jesse Liberty / Siddhartha Rao / Bradley Jones 译者:袁国忠/陈秋萍 【c++上手必备,经典国外书籍最新第6版,中文高清版】

    c++中<cstdlib>的底层实现

    c++中&lt;cstdlib&gt;的底层实现 c++中&lt;cstdlib&gt;的底层实现 c++中&lt;cstdlib&gt;的底层实现 c++中&lt;cstdlib&gt;的底层实现 c++中&lt;cstdlib&gt;的底层实现 c++中&lt;cstdlib&gt;的底层实现 c++中&lt;cstdlib&gt;的底层实现 c++中&lt;cstdlib&gt;的底层实现 ...

Global site tag (gtag.js) - Google Analytics