竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~
公众号: C++学习与探索 | 个人主页: rainInSunny | 个人专栏: Learn OpenGL In Qt
公众号: C++学习与探索 | 个人主页: rainInSunny | 个人专栏: Learn OpenGL In Qt
文章目录
- 指针
- 普通指针
- 函数指针
- 注意事项
- 引用
- 左值引用
- 右值引用
- 注意事项
- 指针和引用区别
指针
普通指针
指针是一个变量,它存储的是另一个变量的内存地址。通过指针,我们可以直接访问或修改存储在内存中的值。基本使用如下:
// 声明指针:要声明一个指针变量,需要在类型前面加上*符号。例如,声明一个指向整数类型的指针变量
int* ptr;// 指针赋值:可以通过取地址符&将变量的地址赋给指针变量。例如,将整数变量num的地址赋给指针ptr
int num = 10;
int* ptr = #// 解引用指针:通过解引用操作符*可以访问指针所指向的变量的值。例如,访问指针ptr所指向的整数变量的值
int value = *ptr; // value现在等于num的值,即10// 修改指针所指向的变量的值:通过解引用操作符*可以修改指针所指向的变量的值。例如,修改指针ptr所指向的整数变量的值
*ptr = 20; // 现在num的值变为20// 空指针:空指针是指不指向任何有效内存地址的指针,通常用nullptr表示
int* ptr = nullptr;// 指针常量:指针本身是一个常量,即指针的值(即所指向的内存地址)不能改变,但指针所指向的值可以改变。声明指针常量时通常在指针变量名前面加上const关键字。例如:
int a = 0;
int b = 1;
int* const p1 = &a;
p1 = &b; // 错误,指针指向的地址不可以改变
*p1 = 2; // OK,指针指向的值可以改变// 常量指针:指针指向的值是一个常量,即指针所指向的值不能改变,但指针本身的值(即所指向的内存地址)可以改变。在声明常量指针时通常在*前面加上const关键字。例如:
const int* p2 = &a;
p2 = &b; // OK,指针指向的地址可以改变
*p2 = 2; // 错误,指针指向的值不可以改变// 指向常量的的指针常量:将上面两者结合,例如:
const int* const p3 = &a;
p3 = &b; // 错误,指针指向的地址不可以改变
*p3 = 2; // 错误,指针指向的值不可以改变
函数指针
函数指针是指向函数的指针,可以用来动态地调用不同的函数。基本使用如下:
typedef int (*funcPtr)(int, int); // 定义返回值为int,函数参数为(int, int)的函数指针类型
int add(int a, int b)
{return a + b;
}
funcPtr funcAdd = add; // 将add函数地址赋值给函数指针funcAdd
int result = funcAdd(1, 2); // 通过funcAdd调用函数add
注意事项
- 使用指针之前,务必对指针进行初始化,可以将指针初始化为nullptr或指向有效的内存地址。
- 避免使用未初始化的指针或已经释放的指针,这会导致未定义行为或程序崩溃。
- 当浅拷贝一份指针的时候,确保使用它时它指向的对象还在生命周期内。
- 在进行指针类型转换时要谨慎,确保转换后的指针类型匹配,避免出现类型不匹配导致的问题。
引用
左值引用
- 左值:可以取地址的对象就是左值。
- 左值引用:左值引用就是对左值的引用,给左值取别名。主要作用是避免对象拷贝。
- 使用场景:一般用于函数参数传递,避免对象拷贝。如果用于接收函数返回值,需要保证返回值在离开函数作用域仍然处在生命周期内。
int& ra = a;
int& r = *p;
const int& rb = b;
右值引用
- 右值:不能取地址的对象就是右值。
- 右值引用:右值引用就是对右值的引用,给右值取别名。主要作用是把延长对象的生命周期,一般是延长到作用域的scope之外。
- 使用场景:作为移动构造函数的参数,作为
std::move
的接收者。
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);
int&& rr4 = std::move(a);
注意事项
- 左值引用只能引用左值,不能直接引用右值。但是const左值引用既可以引用左值,也可以引用右值。
- 在 C++11标准产生之前,是没有右值引用这个概念的,当时如果想要一个类型既能接收左值也能接收右值的话,需要用const左值引用,比如标准容器的push_back接口:
void push_back (const T& val)
。也就是说,如果const左值引用不能引用右值的话,v.push_back(1);
写法就不行了。
- 在 C++11标准产生之前,是没有右值引用这个概念的,当时如果想要一个类型既能接收左值也能接收右值的话,需要用const左值引用,比如标准容器的push_back接口:
- 右值引用引用右值,会使右值被存储到特定的位置。也就是说,右值引用变量本身其实是左值,可以对它取地址和赋值。
指针和引用区别
- 定义和初始化:
- 指针需要通过 * 符号来声明和初始化,例如:
int* ptr = #
- 引用在声明时不需要使用特殊符号,直接通过 & 符号初始化,例如:
int& ref = num;
- 指针需要通过 * 符号来声明和初始化,例如:
- 空值:
- 指针可以指向空值(nullptr),即不指向任何对象或地址。
- 引用在声明后必须引用一个对象,不能指向空值。
- 重新赋值:
- 指针可以被重新赋值指向不同的对象或空值。
- 引用一旦初始化后,不能再引用其他对象,引用变量本身就是其所引用对象的别名。
- 算术运算:
- 指针可以进行算术运算,指针加减整数会移动指针指向的位置。
- 引用不支持算术运算,因为引用本质上是对象的别名。
- 传递给函数:
- 当作为函数参数时,指针可以传递空指针,也可以传递指向数组或动态分配内存的指针。
- 引用作为函数参数时,可以确保不为空,且不需要进行空值检查。
- 修改对象:
- 通过指针可以修改所指向对象的值。
- 通过引用也可以修改引用对象的值,因为引用本质上是对象的别名。
关注公众号:C++学习与探索,有惊喜哦~