指针的基本概念:
指针是C++语言中的重要概念,是一种存储变量地址的变量,它的作用是可以通过指针间接访问内存。通过指针的方式,我们可以读取或修改内存中的数据。
指针变量的定义和使用:
定义指针的语法:数据类型 *指针变量名;
指针变量的值是一个地址,可以通过解引用(指针前加一个*)的方式来找到该地址指向的内存单元。使用指针的过程就是对指针进行赋值,指针所记录的变量地址可以根据需要进行修改。
指针所占内存空间:
在32位操作系统下,指针变量占用4个字节,而在64位操作系统下,指针变量占用8个字节。指针变量所占空间不受数据类型的影响,不管指向的是何种类型的变量,在内存中,它们都是以字节为单位存储的。
空指针和野指针:
空指针是指针变量指向内存编号为0的空间,用途是初始化指针变量。空指针指向的内存是不可以访问的。而野指针则指向非法的内存空间,例如指针变量没有被初始化,或者已经被释放的内存单元。操作野指针可能会导致程序崩溃或出现不可预知的错误,因此应该避免使用野指针。
const修饰指针:
const修饰指针有三种情况:
1.常量指针:const int *p;
指针的指向可以修改,但是指针指向的值不能修改。
2.指针常量:int * const p;
指针的指向不可以修改,但是指针指向的值可以修改。
3.指向常量的指针常量:const int * const p;
指针的指向和指针指向的值都不能修改。
指针和数组:
数组名可以看作是指向数组第一个元素的指针。通过指针访问数组中的元素,可以通过定义指向数组首元素的指针来实现。例如,int *p = arr; 可以将指针p指向数组arr的第一个元素。利用指针访问整个数组元素,只需要通过指针的加减运算来实现。
指针和函数:
指针可以作为函数参数,实现值传递和地址传递。与值传递不同,地址传递通过传递变量地址来改变变量本身,因此可以用来实现交换变量值等操作。指针和数组一起使用可以实现更多的功能,例如利用冒泡排序对数组进行排序。在函数中,对于指向数组的指针,可以通过数组元素的下标来访问数组中的元素。
当涉及指针的使用时,需要特别注意以下几点:
1. 指针的初始化:在使用指针变量之前,必须初始化它。未初始化的指针是一个野指针,它的值是不确定的,访问野指针会导致未定义的行为。
2. 空指针检查:在使用指针之前,最好检查它是否为空指针(即指向内存编号为0的地址)。对空指针进行解引用操作会导致程序崩溃。
3. 指针的释放:在动态分配内存时,要记得在不需要使用该内存的时候释放指针所指向的内存。忘记释放指针可能导致内存泄漏。
4. 悬空指针:悬空指针是指不能访问到有效的内存地址的指针。在释放了指针所指向的内存后,要将指针设置为nullptr,避免产生悬空指针。
5. 数组越界:指针和数组结合使用时,要注意不要越界访问数组。越界访问会导致不可预测的行为或者程序崩溃。
6. 指针的生命周期:确保在指针使用期间,它所指向的内存块是有效的。在指针超出有效范围之后仍然使用指针可能导致错误。
7. 野指针和释放后指针:避免使用野指针和释放后的指针,它们都是指向无效内存的指针,可能导致程序崩溃或者内存错误。
指针是C++语言中非常强大同时也容易出错的特性,因此在使用指针时需要小心并确保正确性。 Debugging时,内存错误可能导致程序崩溃,应用程序的稳定性和安全性都取决于对指针的正确管理和使用。
- 指针的定义和使用
#include <iostream>
using namespace std;
int main () {
int *p = NULL; // 定义一个空指针
int num = 10;
p = # // 指针赋值,同时指向num变量的地址
cout << "num的地址是:" << &num << endl;
cout << "指针p指向的地址是:" << p << endl;
cout << "指针p指向的值是:" << *p << endl; // 指针解引用,输出num的值
return 0;
}
输出:
num的地址是:0x7ffeefbff3ec
指针p指向的地址是:0x7ffeefbff3ec
指针p指向的值是:10
代码说明:
首先定义了一个空指针p,并将其指向了num变量的地址。然后,我们可以通过指针解引用的方式间接访问num变量的值,输出它指向的地址和值。指针的使用可以让我们在需要时间接地操作内存。
- const修饰指针
#include <iostream>
using namespace std;
int main () {
const int MAX = 10;
int num = 20;
const int *p1 = &MAX; // 常量指针,指向MAX常量
int * const p2 = # // 指针常量,指向num变量
const int * const p3 = &MAX; // 指向常量的指针常量,指向MAX常量
cout << "p1指向的值是:" << *p1 << endl;
*p2 = 30; // 修改指针指向的变量num的值
cout << "p2指向的值是:" << *p2 << endl;
// p1++; // 不能修改指针指向的地址
// p3 = # // 不能修改指针指向的地址
return 0;
}
输出:
p1指向的值是:10
p2指向的值是:30
代码说明:
常量指针(const int *p1)表示指向常量的指针,即指针所指向的值不可以修改,而指针本身可以修改。
指针常量(int * const p2)表示指针常量,即指针所指向的地址不可以更改,指针所指向的值可以修改。
指向常量的指针常量(const int * const p3)表示既不能更改指针所指向的地址,也不能更改所指向的值。
注意:当一个指针被const修饰时,意味着它只能在初始化时指向某个对象,并在其整个生命周期中指向该对象。指针的地址和所指向的对象是紧密联系的,尤其是在使用指向常量的指针时,需要确保指针所指的对象的生命期大于等于指针在使用期间。
- 指针和函数
#include <iostream>
using namespace std;
void change(int *p);
int main () {
int num = 10;
int *p = #
cout << "变换之前:" << *p << endl;
change(p);
cout << "变换之后:" << *p << endl; // 通过指针改变了num的值
return 0;
}
void change(int *p) {
*p = 20; // 通过指针修改num变量的值
return;
}
输出:
变换之前:10
变换之后:20
代码说明:
在change函数中,我们利用指针参数p修改了p所指向的变量的值。在主函数中,我们定义了一个指向num变量的指针p,并将其传递给change函数。当change函数执行时,