C++基础(8.2)——引用变量

引用变量

引用变量是C++的一种复合类型,是已定义变量的别名,主要用途是做函数的参数。通过将引用做参数,函数将使用原始数据而非副本。这样除指针之外,引用也为函数处理大型大型结构提供了一种方便的途径,同时对于设计类来说,引用也是不可避免的

  • 创建引用变量
int rats;
int & rodents = rats; // makes rodents an alias for rats
/* &不是地址运算符,而是类型标识符,int &指的是指向int的引用 */
  • 引用与指针的区别
  1. 指针可以先声明在赋值,而引用必须在声明时赋值
/* 指针 */
int rat;
int * rodents;
rodents = &rat; // OK

/* 引用 */
int rat;
int & rodents;
rodent = rat;	// No, you can't do this.
  1. 引用接近const指针,必须在创建时进行初始化,一旦与某个变量关联起来,就一直效忠于它
int a  = 3;
int & b = a;

int c = 50;
b = c;
std::cout << "variable c value is " << c  << ", storage address is " << &c << std::endl;
std::cout << "variable b value is " << b  << ", storage address is " << &b << std::endl;
std::cout << "variable a value is " << a  << ", storage address is " << &a << std::endl;

$ ./example
variable c value is 50, storage address is 0x7fff609c05f0
variable b value is 50, storage address is 0x7fff609c05f4
variable a value is 50, storage address is 0x7fff609c05f4
/* 由上得知, b与a的地址相同, 而与c的地址不同,由于b是a的别名, 因此b=c, 与a=b等效, 
结论:可以通过初始化声明来设置引用,但不能通过赋值操作来设置
*/
  • 将引用用作函数参数
    引用常用作函数参数,使得函数中变量名成为调用程序中的变量的变量,这种传递参数的方法称为按引用传递。C++新增的这项特性是对C语言的超越,C语言只能按值传递,按值传递导致被调用函数使用调用程序的值的拷贝。C语言也有避开按值传递的限制,采用按指针传递的方式

  • 引用的属性和特别之处

    /* 临时变量、引用参数和const */
    
    void test(int ra) {
    	cout << ra << endl;
    }
    
    int a = 1;
    int b = test(a + 1.1);  // 不合理,因为表达式a+1非变量
    /* 如果实参与引用参数不匹配,C++将生成临时变量。当前,仅当参数为const引用时,
    C++才允许这样做 */
    
    /* 如果引用参数是const, 则编译器将在下面两种情况下生成临时变量: 
    1. 实参的类型正确,但不是左值
    2. 实参的类型不正确,但可以转换为正确的类型
    */
    
    /* 在早期的C++中*/
    void swapr(int & a, int & b) {
    	int temp;
    	temp = a;
    	a = b;
    	b = temp;
    }
    long a = 3, b = 5;
    swapr(a, b);
    // 在早期C++较为宽松的规则下,执行这样的操作时,因为类型不匹配,因此编译器将创建两个临时int变量,并分别初始化为3和5,然后交换临时变量的内容,而a和b保持不变
    

注意: 如果函数调用的参数不是左值或与相应的const引用参数的类型不匹配,则C++将创建类型正确的匿名变量,将函数调用的参数的值传递给匿名变量,并让参数来应用该变量

尽可能的使用const:

  • 使用const可以避免无意中修改数据的编程错误
  • 使用const使函数能够处理const和非const实参,否则只能接受非const数据
  • 使用const引用使函数能够正确的生成临时变量
    ** 右值引用:**
	/* C++11新增了另一种引用——右值引用(rvalue reference) 这种引用可指向右值,使用&&声明 */
	double && rref = sqrt(36.00);	// not allowed for double &
	double j = 15.0;
	double && jref = 2.0 * j + 18.5; // not allowed for double &
	cout << rref << endl; // display 6.0
	cout << jref << endl; // display 48.5
	/* 新增右值引用的主要目的是,让库设计人员能够提供有些操作的有效实现, C++ primer plus chapter 18详细描述如何使用右值引用来实现移动语义(move semantics)。以前的引用(使用&声明的引用)现在称为左值引用 */
  • 将引用用于结构
    引入引用的主要目的是用于结构和类,而非内置的基本类型
    // 返回引用还不是非常理解, 暂时写个相对简单的例子
    /* 函数返回引用 */
    struct Student {
        int age;
        std::string name;
    };
    
    // 方式1
    Student & test_return_quote(Student & a)
    {
        a = {25, "LiuDeHua"};
        std::cout << "init success" << std::endl;
        
       // Student c  = {20, "aaa"};
        //return c; 不可以返回已经不再存在的内存单元
        
        return a;
    }
    
    /*	另一种方法是:
    	使用new来分配新的存储空间,并返回指向该内存空间的指针
    	而调用test_return_quote2()时隐藏了对new的调用,应该使		用delete释放,或者使用auto_ptr模板以及C++11新增的unique_ptr自动完成释放工作
    */
    Student & test_return_quote2(Student & a)
    {
        Student *pt;
        *pt = a;
        return *pt;
    }
    
    int main()
    {
    	Student  s;
        Student a;
        s = test_retuen_quote(a);
        std::cout << s.age << std::endl;
        std::cout << s.name << std::endl;
        
        /* 传统返回机制与返回应用的不同, 传统返回机制与按值传递函数类似; 
        计算关键字return后面的表达式,并将结果返回给调用函数。
        从概念上说, 这个值(test_return_quote中的a)复制到一个临时位置,
        然后将这个值拷贝给调用方s。 但在返回引用时,将直接把a赋值到s, 其效率更高 */
    	return 0;
    }
    
    注意: 返回引用的函数实际上是被引用的变量的别名
    返回引用时需注意的问题:
    1. 返回引用时,应避免返回函数终止时不再存在的内存单元引用
    2. 如果用new来分配新的存储空间,并返回指向该内存空间的指针时,应该做到及时delete或智能指针及时释放
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值