C++ 教程 在线

2642passing-parameters-by-references

举个例子,有这么一个结构体:

struct Demo 
{
  char name[10000];
  int  count;
};
int main()
{
  Demo my_demo = {0};
  Demo *my_demo_p = &my_demo;
  Demo &my_demo_ref = my_demo;
  
  // 方式1:传递实参  
  func1(my_demo);
  // 方式2:传递指针  
  func2(my_demo_p);
  // 方式3:传递引用  
  func3(my_demo_ref);
  return 0;
}
如上所示,参数传递可以有三种方式,则三种函数可以这样定义:
// 方式1:传递实参 
void func1(Demo demo)
{
  cout << demo.name;
}
// 方式2:传递指针  
void func2(const Demo *demo_p)
{
  cout << demo->name;
}
// 方式3:传递引用  
void func3(const Demo &demo_ref)
{
  cout << demo.name;
}

可以看出,引用和实参的使用方式很像,但注意以下几点:

  • 从内存使用的角度来说,传递实参,则会将数据拷贝过去(创建了副本),即 func1 对传入的数据做任何修改,都不会影响 my_demo。
  • 既然传递实参要创建副本,就意味着效率更低。例子中结构体的 name 成员长度为 10000,就是要突出这个效率问题。

引用和指针也很像,它们都不会创建副本,因此效率都很高。它们的主要区别在于:

  • 选择成员的时候,引用使用点 . 来查找,而指针则使用 -> 来查找。
  • 指针可能传递一个 NULL 过来,因此在使用前必须检查有效性;引用则必然代表某个对象,不需要做此检查。

PS: 在代码中加上 const 关键字的目的,是不希望 func2 和 func3 去修改原始数据,因为函数仅仅是为了打印出 name。

2641passing-parameters-by-references

以引用作为参数的函数,可以把变量传入,但不能传入常量。

#include <iostream>
using namespace std;
int hls(int& a1, int& a2, int& b1, int& b2) //定义行列式函数
{
   int temp;
   temp=a1*b2-a2*b1;
   return temp;
}
int main()
{
   int x1=11; int x2=9;
   int y1=15; int y2=14;  //定义矩阵
   int result;  //行列式运算结果
   result=hls(x1,x2,y1,y2);   //result=hls(11,9,15,14)会报错
   cout << result << endl;
   return 0;
}

2640cpp-pointers-vs-arrays

经过实验确实如此我在教程中的实例里发现, ptr=var; 这句话改为 ptr=&var[0]; 也可以,经过实验确实如此。

#include <iostream>
using namespace std;
const int MAX=3;
int main ()
{
   int var[MAX] = {10, 100, 200};
   int *ptr=NULL;
   ptr=var;    //这句话改为"ptr=&var[0];"也可以
   for(int i=0; i<3; i++)
   {
    cout << "var[" << i << "]的值为:" << *ptr << ",内存地址为:" << ptr << endl;
    ptr++;     //移到下一个位置
   }
   system("pause");
   return 0;
}

2639cpp-pointer-arithmetic

感觉楼上的几位说的有点矛,我直接跑了一下看结果(建议直接看结论):

short int height[10]; //int型的数组(short int 每个数据2字节)
cout <<  "height       "<< height << endl 
     <<  "height+1     "<< height + 1 << endl
     <<  "&height[0]   " <<  &height[0] << endl
     <<  "&height+1    "<< &height + 1<< endl
     <<  "height+9     "<< height+9 << endl
     << "height+10    " << height + 10 << endl;

结果如下:

height       0136F900
height+1     0136F902
&height[0]   0136F900
&height+1    0136F914
height+9     0136F912
height+10    0136F914

可以看到:

  • height 与 &height[0] 值相等。
  • height+1 = height + 2 字节 = height + 1 个 short int 也即 一个数组元素。
  • height+9 为 height[] 中最后一个元素的地址,height+10 为该数组结束后的第一个地址。
  • &height +1=height+10,即执行 &height+1 的结果是地址跳到整个数组之后第一个地址。

结论:bpink(3楼)说的是对的。

2638cpp-pointer-arithmetic

对楼上的 & 进行补充说明,& 并不是不能用在数组名上,只是用在数组名和数组名[i]有所区别。例如:

int height[10];//int型的数组
cout << &height << endl;//&用在数组名上
cout << &height[0] << endl;//&用在数组第一个元素上

上面 &height[0] 就是取得是数组第一个元素的地址,假设地址为 1000;&height 是直接对数组名进行取地址,这个时候就是取得是 height 整个数组的地址,指向包含 10 个元素的 int 型数组,地址范围为 1000~1036;

我们知道 height 等价于 &height[0],height+1 会将地址加 4 个字节;但 &height+1 就是将地址增加 10*4 个字节。