C++ 引用详解(1)

目录

一、引用 —>(常量指针)

二、C++ 引用 与 指针的区别

三、引用作为函数的参数

四、把引用作为返回值 函数做左值使用

五、常量引用


一、引用 —>(常量指针)

  1. 引用的作用:给变量起别名 引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量,此时引用的地址和变量的地址绑定即为变量地址。

  2. 实例

     #include 
     using namespace std;
     ​
     int main() 
     {
     ​
         int a = 666;        // 定义一个变量
         int &b = a;         // 引用变量---> 给 a 取一个别名 b 意味着 b 和 a 引用的是同一块内存空间,对b的修改会直接影响到a的值。
         // int b = a; 与 int &b = a; 不同之处在于 前者会开辟一个内存空间,然后把 a 的值赋给 b,之后 修改 b 的值不会影响到 a 的值
         
         // 输出 a 和 b 结果相同
         cout << "a = " << a << endl;
         cout << "b = " << b << endl;
         
         // 用引用改变变量
         b = 100;
         
         // b 改变了 由于是引用所以 a 也相应改变为 100
         cout << "a = " << a << endl;
         cout << "b = " << b << endl;
     ​
         system("pause");
     ​
         return 0;
     }
    结果
    
    a = 666
    b = 666
    a = 100
    b = 100
    请按任意键继续. .

二、C++ 引用 与 指针的区别

  • 不存在空引用。引用必须连接到一块合法的内存。

  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。

  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。

实例

#include 
 using namespace std;
 ​
 int main()
 {
   int a = 100;
   int &b = a;       // 定义引用时初始化引用
 ​
   cout << "a = "<< a <<", b = "<< b < a = 100, b = 100
 a address = 0xbfce21e4
 b address = 0xbfce21e4
 ===================================
 a = 50, b = 50, c = 50
 a address = 0xbfce21e4
 b address = 0xbfce21e4
 c address = 0xbfce21e8

从结果可以看出,第十五行虽然在调用 b = c; 后引用 b 的值变为 50,但 b 所指向的地址空间还是指向了 a,没有发生改变,说明 b = c; 只是将 c 的值赋值给引用 b 所指向的变量,没有改变引用的指向。

注意,引用在定义时需要添加&,在使用时不能添加&,使用时添加&表示取地址。如上面代码所示,第 7行中的&表示引用,第 10 行中的&表示取地址。除了这两种用法,&还可以表示位运算中的与运算。

三、引用作为函数的参数

作用:函数传参时,可以利用引用的技术 将实参和形参绑定在一起,让它们都指代同一份数据。如果在函数体中修改了形参的数据,那么实参的数据也会被修改,从而拥有“在函数内部影响函数外部数据”的效果,达到和指针一样的效果但引用比指针更简洁。

 #include 
 using namespace std;
 ​
 // 1. 值传递
 void mySwap01(int a, int b)
 {
     int temp = a;
     a = b;
     b = temp;
 }
 ​
 // 2. 地址传递
 void mySwap02(int* a, int* b) 
 {
     int temp = *a;
     *a = *b;
     *b = temp;
 }
 ​
 // 3. 引用传递
 void mySwap03(int& a, int& b) 
 {
     int temp = a;
     a = b;
     b = temp;
 }
 ​
 int main() 
 {
     int a = 10;
     int b = 20;
 ​
     mySwap01(a, b);
     cout << "a:" << a << " b:" << b << endl;
 ​
     mySwap02(&a, &b);
     cout << "a:" << a << " b:" << b << endl;
 ​
     mySwap03(a, b);
     cout << "a:" << a << " b:" << b << endl;
 ​
     system("pause");
 ​
     return 0;
 }
注意:以引用作为参数的函数,可以把变量传入,但不能传入常量。

四、把引用作为返回值 函数做左值使用

实例

 #include 
 using namespace std;
 ​
 // 不能返回局部变量的引用  返回的局部变量引用在第二次使用时数据会发生改变
 int& test01() 
 {
     int a = 10; // 局部变量
     return a;
 }
 ​
 // 返回静态变量引用
 int& test02() 
 {
     static int a = 20;
     return a;
 }
 ​
 int main() 
 {
     // 不能返回局部变量的引用  
     int& ref = test01();
     cout << "ref = " << ref << endl;
     cout << "ref = " << ref << endl;
 ​
     // 如果函数做左值,那么必须返回引用
     int& ref2 = test02();       // 返回静态变量引用 给test02() 取一个别名ref2
     cout << "ref2 = " << ref2 << endl;
     cout << "ref2 = " << ref2 << endl;
 ​
     test02() = 1000;            // 函数返回的是引用a 修改test02()等价于修改 a 
 ​
     cout << "ref2 = " << ref2 << endl;      // ref2 是test02() 的别名 此时打印 ref2 即打印test02()
     cout << "ref2 = " << ref2 << endl;
 ​
     system("pause");
 ​
     return 0;
 }

结果

 ref = 10         
 ref = 2078972296  // 第二次使用数据为随机
 ref2 = 20
 ref2 = 20
 ref2 = 1000
 ref2 = 1000
注意:
  1. 不能返回局部变量的引用。因为局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。,但是,可以返回一个对静态变量的引用。

  2. 不能返回函数内部new分配的内存的引用或者指针。

    1. 内存泄漏:当你在函数内部使用 new 运算符分配内存时,你会在堆内存中创建一个对象,并返回一个指向该对象的指针。如果你将这个指针传递出函数,或者在函数外部保留对它的引用,但没有合适的方式来释放这块内存,那么就会导致内存泄漏。这意味着你的程序会持续占用越来越多的内存,最终可能导致程序崩溃。

      1. 实例

        #include 
        
        int* createInt() 
        {
            int* ptr = new int(42);
            return ptr;
        }
        
        int main() 
        {
            int* result = createInt();
            std::cout << *result << std::endl;
            delete result;     // 释放内存
            std::cout << *result << std::endl; // 这里可能会导致问题
            return 0;
        }
        

    2. 访问已释放的内存:如果你在函数内部创建了一个对象,并返回一个指向该对象的指针,然后在函数结束后释放了这块内存,那么在函数外部仍然持有对该内存的引用,就会导致悬空指针问题。当你尝试访问这块内存时,程序会引发未定义的行为,可能会导致崩溃或不可预测的结果。

五、常量引用

常量引用主要用来修饰形参,防止误操作修改引用

实例

// 常量引用使用的场景,通常用来修饰形参
void showValue(const int& v) 
{
	// v += 10;  // 这里不能修改变量值
	cout << v << endl;
}

int main() 
{
	// int& ref = 10;  引用本身需要一个合法的内存空间,因此这行错误
	// 加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;
	const int& ref = 10;

	// ref = 100;  // 加入const后不可以修改变量
	cout << ref << endl;

	// 函数中利用常量引用防止误操作修改实参
	int a = 10;
	showValue(a);

	system("pause");

	return 0;
}

结果

10
10
请按任意键继续. . .

下一篇:C++函数重载及函数的默认参数

你可能感兴趣的:(C++基础,c++,算法,开发语言)