C++引用类型全解析
时隔很久终于又开始补学之前的知识了,话不多说,开始整理笔记
类型分类
1.内置类型(属于基本类型)
整型(Integer Types)
int:标准整型,通常为4字节。
short:短整型,通常为2字节。
long:长整型,通常为4或8字节
long long:更长的整型,通常为8字节。
unsigned:无符号整型,不支持负数。
unsigned short、unsigned long、unsigned long long:对应的无符号版本。
字符型(Character Types)
char:字符型,通常为1字节。 (char c=“a”;)
wchar_t:宽字符型,通常为2或4字节(用于表示Unicode字符)。
char16_t、char32_t:用于表示UTF-16和UTF-32编码的字符。
浮点型(Floating Point Types)
float:单精度浮点型,通常为4字节。
double:双精度浮点型,通常为8字节。
long double:扩展精度浮点型,通常为8字节或16字节(取决于平台)。
布尔型(Boolean Type)
bool:布尔型,表示真(true)或假(false)。
2. 复合类型
复合类型是由内置类型或其他复合类型组合而成的类型,主要包括以下几种:
数组(Array)
一组相同类型的数据元素,可以通过索引访问。
结构体(Struct)
一种用户定义的数据类型,可以包含不同类型的数据成员。
联合体(Union)
与结构体类似,但所有成员共享同一内存位置,只有一个成员可以在任何给定时间存储值。
枚举(Enum)
一种用户定义的类型,用于定义一组命名的整型常量。
类(Class)
C++的面向对象编程特性,允许定义包含数据和成员函数的复杂数据类型。
指针(Pointer)
指向其他类型的内存地址,可以用来动态分配内存和实现复杂的数据结构。
引用(Reference)
对现有变量的别名,提供了对变量的另一种访问方式。
注意:Std::string name =”xxxl”; 这不是字符类型,是字符串类型,属于复合类型,这是得益于std作用域下,定义了一个类,只要和这个类相关的,我们叫做类类型-->复合类型,String 里是包含char的
总的来说:判断是否为复合类型在于:是不是自己定义的类,c++大佬定义的,STL容器定义的类(比如 map,vector都是属于类的复合类型),其余的一般都是基本类型。
引用类型
定义:
C++ 中的引用类型是一种复合类型,它是对另一个变量的别名。在C++中使用引用,可以让我们直接访问和操作另一个变量的内存地址,而不需要通过指针的解引用操作。引用在语法上比指针更简洁,且在许多情况下更安全。
可能大家对上面文字理解太吃力,那我们试着想一下变量的存储:

可以看出:
定义一个变量a,并且初始化为100,编译器会为变量a开辟空间,绿色的是开辟的空间,存储100,这个空间的首地址为0x2be3,也就是变量a的地址。
地址大家可以裂解为门牌号,我们可以通过门牌号找到绿色的家,a是绿色的家的名字,进而取出家里的物品,数据100可以理解为物品。
执行b = a,将a赋值给b后,编译器又开辟了一块空间,存储100,这个空间的首地址为0x3f2b。 打个比方,我们又创建了一个家,家的名字是b,家里也存储了100这个物品,但是这个家的地址和a的不一样。
演示:

我们同样定义了一个变量a,并为它开辟空间,存储100,空间的首地址为0x2be3,我们定义了一个引用b,它是a的别名,所以b的地址和a的地址都一样,都是0x2be3
从上述图形可以看出,引用是变量的别名。
写法:
// 定义变量a int a = 100; // 定义引用b并且指向a, b就是a的别名 int &b = a;
这个 int & 表示的就是b是int类型的引用变量,如果你想查看a和b的地址是否真的相同,那我们可以这样写:
std::cout << "a的地址为:" << &a << std::endl; std::cout << "b的地址为: " << &b << std::endl;
在a和b前加 & 即可输出他们的地址:

可以看到a和b的地址相同。也证明了a和b是指向同一个地址空间。所以我们修改a的值,b的值也会变
// 定义变量a int a = 100; // 定义引用b并且指向a, b就是a的别名 int &b = a; // 输出a和b的值 std::cout << "a的值:" << a << std::endl; std::cout << "b的值: " << b << std::endl; // a和b是指向同一个变量。所以我们修改a的值,b的值也会变 a = 200; std::cout << "修改a的值后,a和b的值分别为:\n" << a << std::endl; std::cout << b << std::endl;

可以看到修改了a的值,b也跟着变化了,接下来我们修改b的值
// 修改b的值,a的值也会变 b = 300; std::cout << "修改b的值后,a和b的值分别为:\n" << a << std::endl; std::cout << b << std::endl;
程序输出:

可以看到b的值修改了,a的值也变化了
// 定义c,存储a的值 int c = a; std::cout << "c的值:" << c << std::endl; // 修改c的值 c = 400; std::cout << "修改c的值后,c为:" << c << std::endl; std::cout << "修改c的值后,a和b的值分别为:\n" << a << std::endl; std::cout << b << std::endl;

可以看到c为a的副本,修改c不影响到a和b。
特性:
1.必须初始化:引用在创建时必须被初始化,它必须指向某个已存在的对象。
2.一旦绑定,不可改变:引用一旦被初始化后,它将一直保持与其初始对象的绑定,不能改变为另一个对象的引用。
3.没有空引用:引用必须指向某个对象,不能存在空引用(但会有空指针)
#include <iostream>
int main() {
int a = 100;
int &b = a; // b是a的引用
std::cout << "a = " << a << ", b = " << b << std::endl; // 输出: a = 100, b = 100
b = 200; // 更改b的值也会更改a的值
std::cout << "a = " << a << ", b = " << b << std::endl; // 输出: a = 200, b = 200
// int c = 300;
// 表示修改b的值为c的值
// b = c;
return 0;
}注意事项:
引用主要用于函数参数和返回值,以及类的成员变量等场景,以提供对原始数据的直接访问,从而提高程序的效率和可读性。
引用可以是const的,这表示你不能通过引用来修改它所指向的对象的值。
引用在内部实现上通常是通过指针来实现的,但它们在语法和用途上与指针有显著的不同。引用提供了更直观、更安全的访问方式。
这里普及一下const是什么?
const=constant,只读,不可修改的,表示常量,作用:修饰变量/参数/函数/指针,声明它是只读,不能被赋值修改,编译器会检查防止误改
左值引用和右值引用
在C++中,左值(lvalue)和右值(rvalue)是表达式的两种基本分类,它们决定了表达式的结果在内存中的位置和状态。左值通常指的是具有持久状态的对象,它们有明确的内存地址,可以被多次赋值。而右值通常是临时的、没有持久状态的值,它们通常没有内存地址,或者其内存地址在表达式结束后就变得无效。
C++11引入了右值引用(rvalue reference),用T&&表示,作为对左值引用(lvalue reference,用T&表示)的补充。这一特性极大地增强了C++的表达能力,特别是在资源管理和性能方面。
左右值最大的区别就是:左值可以修改,右值是字面量,不能修改的(函数返回值,临时变量,字面量等),由此产生左值引用和右值引用。
左值引用
左值引用是C++98就有的特性,它允许我们为已存在的对象创建一个别名。左值引用必须被初始化为一个左值,即一个具有持久状态的对象。简单来说:绑定左值的引用
int a = 10; int& b = a; // b是a的左值引用
右值引用
右值引用是C++11新增的特性,它允许我们为右值(即临时对象或即将被销毁的对象)创建一个引用。这样,我们就可以对右值进行更复杂的操作,比如移动语义(move semantics)。
int&& c = 20; // c是整数字面量20的右值引用(但这种情况不常见,通常用于函数参数或返回值)
std::string foo() {
return std::string("Hello, World!"); // 返回的临时字符串是一个右值
}
std::string &&d = foo(); // d是foo()返回的临时字符串的右值引用但请注意,直接绑定一个右值到右值引用(如int&& c = 20;)并不是右值引用的主要用途。右值引用的主要用途是作为函数参数(实现移动语义)和返回值(允许链式调用等)。
移动语义和完美转发
右值引用的引入主要是为了支持移动语义(move semantics),它允许我们在对象被销毁前“窃取”其资源(如动态分配的内存、文件句柄等),而不是进行深拷贝。这可以显著提高性能,特别是在处理大型对象或容器时。
完美转发(perfect forwarding)是另一个与右值引用相关的概念,它允许我们将参数原封不动地传递给另一个函数,无论是左值还是右值。这通过模板和std::forward函数实现。
总结
左值引用(T&)是C++98就有的特性,用于为已存在的对象创建别名。
右值引用(T&&)是C++11新增的特性,用于为右值(即临时对象)创建引用,支持移动语义和完美转发等高级特性。
右值引用的主要用途不是直接绑定到字面量或简单的右值表达式上,而是在函数参数和返回值中,以实现更高效的资源管理和更灵活的代码编写方式。
结语:
快速掌握C++引用类型:从内置类型到复合类型详解!本文用生动比喻帮你理清左值引用、右值引用核心区别,学会移动语义提升代码性能,点击解锁引用初始化、绑定特性与实战技巧,让C++学习更高效
到此这篇关于C++引用类型全解析的文章就介绍到这了,更多相关C++引用类型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


最新评论