(C++)指针和引用

一、引用的概念

不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名。

#include <iostream>
using namespace std;

int mian() {
    int a = 10;
    int* p = &a;
    //内存开辟一段空间,名为a,a内内容为10,定义指针p指向a,即指针p内保存a的地址

    //引用
    //格式:类型& 引用的变量名 = 已定义过的变量名
    int& b = a;//b引用了a,b是a的别名
    int& c = a;
    int& c = b;
    //给刚才开辟的a重新命名为b,c

    cout<<a<<endl;//10
    cout<<b<<endl;//10
    cout<<c<<endl;//10

    c = 20;
    cout<<a<<endl;//20
    cout<<b<<endl;//20
    cout<<c<<endl;//20
    return 0;
}

//引用:
  //1.引用必须初始化;
  int i; // √ 
  int& j; // × 
  //2.一个变量可以取多个别名;
  //3.引用只可以在初始化时引用一次,不能再变成其他变量的别名



int main() {
    int a = 10;
    int& b = a;
    int i = 100;
    b = i;
    //储存10的内存,同时命名为a,b;b = i即把i内值赋值给b;
    //引用在初始化时只能引用一次,之后在=其他变量,看作是赋值
    cout<<b<<endl;//100,且此时a,b均为100
    return 0;
}

二、const 引用->引用常量

#include <iostream>
using namespace std;

int main() {
    int a = 4;
    const int& b = a;
    a = 5;// √ a改变,b也会改变
    b = 5;// × 不能给常量赋值
    return 0;
}

int main() {
    const int a = 10;
    int& b = a;// × 
    const int& b = a;// √ 常量具有常性,只有常引用可以引用常量

    int& c = 20;// × 20是常量,引用是为某个变量起个别名,而且,20的值不可以改变,c的值可以改变,所以不可以这样引用
    const int&c = 20;// √ c是20这块区域的别名

    int d = 10;
    double e = d;//隐式类型的转换(!可能会丢失数据)

    //隐式类型的转换
    (http://img.blog.csdn.net/20180315020214467?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ2lyYWZmZV8yNTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

    double& f = d;// × 实际上是将f命名给了临时变量,因为临时变量不可以更改,所以必须要加const才可以编译通过
    const double& f = d;// √ 
    return 0;
}

三、引用的应用

1.用引用做参数(swap2)

#include <iostream>
using namespace std;

void swap1 (int* l,int* r) {//传进来&a(地址)
    int tmp = *l;//解应用之后为值
    *l = *r;
    *r = tmp;
}

void swap2 (int& l,int& r) {
    int tmp = l;
    l = r;
    r = tmp;
}

void swap3 (int l,int r) {
    int tmp = l
    l = r;
    r = tmp;
}
int main() {
    int a = 10;
    int b = 20;
    swap1(&a,&b);//传地址
    //指针,将a,b的地址传给指针l,r,之后将a,b之内数值交换;

    swap2(a,b);//传引用
    //将a,b引用传入函数,即:int& l = a;将内存a重新命名为l,将l内值改变,即改变同一块内存,a的值,b同理;

    swap3(a,b);//传值
    //这样等同于一般函数,只传值,所以不改变a,b本身的值,交换就没有完成,而且耗费内存和时间,效率很低
    return 0;
}

2.引用做返回值

 #include <iostream>
 using namespace std;

 typedef struct Big {
     int a[10000];
 }Big;

 //传值
 void func1(Big big) {
     //......
 }

 //传指针
 void func2(Big* big) {
     //......
 } 

 //传引用
 void func3(Big& big) {
     //......
 }  

 //传const引用
 void func4(const Big& big) {
     //......
 }

 int  main() {
     Big b1;
     func1(b1);//浪费空间,效率低
     func2(b2);//另外开辟一个指针的空间
     func3(b3);//不需要另外开辟空间,只是给原本的变量起了一个别名
     func4(b4);//***最好使用这个,非但不用额外开辟空间,减少空间消耗;而且里面值改变,外面的值不受影响

}

int Add(int a,int b) {
    int c = a + b;
    return c;
}

int& Add(int a,int b) {
    int c = a + b;
    return c;
}

int main() {
   int ret = Add(1,2);//匿名临时变量,编译器在main里开辟空间,传值返回
   int& ret = Add(1,2);//栈帧内部有一处空间被命名,类型为int&,这段空间内储存c的值;空间存在不确定性,当下一次被占用时很可能改变,或者直接改为随机值
   const int& ret = Add(1,2); //必须加const,这样这段int&类型空间中的值就不能被改变,值可以被一直保存下来,不会随函数的结束而被释放或者占用
}


(http://img.blog.csdn.net/20180326153455768?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ2lyYWZmZV8yNTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

3.汇编层看引用的特性

  • 要返回一个临时变量的引用,出了作用域就已经不存在了
  • 出了作用域,返回的变量还存在,尽量使用引用,减少临时变量的产生(高效,不浪费空间)

4.引用和指针的区别

  • 语法:未开辟空间
  • 汇编层:开辟空间

  • 指针++:+类型大小

  • 引用++:+1(加到变量上去)

注意:空指针解应用会奔溃

猜你喜欢

转载自blog.csdn.net/giraffe_255/article/details/79562561