目录
一、引用 —>(常量指针)
-
引用的作用:给变量起别名 引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量,此时引用的地址和变量的地址绑定即为变量地址。
-
实例
#include <iostream> 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 <iostream>
using namespace std;
int main()
{
int a = 100;
int &b = a; // 定义引用时初始化引用
cout << "a = "<< a <<", b = "<< b <<endl;
cout << "a address = "<< &a <<endl;
cout << "b address = "<< &b <<endl;
cout <<"==================================="<<endl;
int c = 50;
b = c; // 调用引用
cout << "a = "<<a<<", b = "<<b<<", c = "<< c <<endl;
cout << "a address = "<< &a <<endl;
cout << "b address = "<< &b <<endl;
cout << "c address = "<< &c <<endl;
return 0;
}
结果
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 <iostream>
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 <iostream>
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
注意:
-
不能返回局部变量的引用。因为局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。,但是,可以返回一个对静态变量的引用。
-
不能返回函数内部new分配的内存的引用或者指针。
-
内存泄漏:当你在函数内部使用
new
运算符分配内存时,你会在堆内存中创建一个对象,并返回一个指向该对象的指针。如果你将这个指针传递出函数,或者在函数外部保留对它的引用,但没有合适的方式来释放这块内存,那么就会导致内存泄漏。这意味着你的程序会持续占用越来越多的内存,最终可能导致程序崩溃。-
实例
#include <iostream> 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; }
-
-
访问已释放的内存:如果你在函数内部创建了一个对象,并返回一个指向该对象的指针,然后在函数结束后释放了这块内存,那么在函数外部仍然持有对该内存的引用,就会导致悬空指针问题。当你尝试访问这块内存时,程序会引发未定义的行为,可能会导致崩溃或不可预测的结果。
-
五、常量引用
常量引用主要用来修饰形参,防止误操作修改引用
实例
// 常量引用使用的场景,通常用来修饰形参
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++函数重载及函数的默认参数