C++中的指针

简介: C++中的指针

指针允许直接操作内存地址,从而实现对数据的灵活控制。

指针的概念

指针是一个变量,其存储的是另一个变量的内存地址。在C++中,每个变量在内存中都有一个唯一的地址,指针变量可以存储这个地址。声明指针时,需要指定指针所指向的数据类型,例如,int* p;声明了一个指向整型数据的指针变量p

指针运算

  1. 解引用(Dereferencing):使用*操作符获取指针所指向的变量的值。例如,如果p指向一个整数,那么*p就是该整数的值。
  2. 指针加减(Pointer Arithmetic):可以对指针进行加减运算,通常用于遍历数组。例如,p++使指针向后移动到下一个元素(假设是数组的话)。
  3. 比较:指针之间可以进行关系运算,如 <, >, <=, >=, ==, !=,用于比较它们所指向的地址。

指针与数组

在C++中,数组名实际上就是一个指向数组首元素的常量指针。这意味着你可以用指针对数组进行操作,比如遍历数组:

int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr; // ptr现在指向数组arr的首元素
for(int i = 0; i < 5; ++i) {
    std::cout << *(ptr + i) << std::endl; // 通过指针访问数组元素
}

堆内存分配

C++提供了两种内存分配方式:栈(stack)和堆(heap)。栈内存由编译器自动管理,而堆内存需要手动管理。

  • 栈内存分配:局部变量通常存储在栈上,生命周期与定义它的函数或代码块相同。
  • 堆内存分配:使用new操作符在堆上动态分配内存。当不再需要时,应使用delete释放内存。

例如,动态分配一个整型数组:

int* heapArr = new int[5]; // 在堆上分配一个大小为5的整型数组
heapArr[0] = 1;
// ... 对其他元素赋值
delete[] heapArr; // 使用完毕后释放内存

const指针

const指针用来表示指针所指向的数据是不可更改的。有两种主要的用法:

  1. 指向const的指针:指针指向的值不能被改变,但指针本身可以指向另一个值。声明形式如const int* ptr,意味着ptr指向的整数是常量。
const int num = 5;
const int* pConst = &num; // pConst指向一个常量整数
// *pConst = 10; // 错误:不能通过pConst修改num的值
  1. const指针:指针一旦初始化后,就不能再指向其他地址,但指向的数据可以修改。声明形式如int* const ptr
int num = 5;
int* const pConstAddr = &num; 
*pConstAddr = 10; // 正确:可以通过指针修改num的值
// pConstAddr = &anotherNum; // 错误:不能改变pConstAddr的地址

指针与函数

  1. 函数指针:指向函数的指针,可以用来存储函数的地址,进而通过指针调用函数。
void greet() { std::cout << "Hello!" << std::endl; }
void (*funcPtr)() = &greet; // 定义一个函数指针并初始化
funcPtr(); // 通过函数指针调用greet函数
  1. 指针函数:返回值为指针的函数。
int* returnIntPtr() {
    static int value = 10;
    return &value;
}
int main() {
    int* ptr = returnIntPtr();
    std::cout << *ptr << std::endl; // 输出10
}

字符指针

字符指针通常用来指向字符串或者单个字符,可以用来操作字符串。

char str[] = "Hello";
char* cPtr = str; // cPtr指向字符串"Hello"
std::cout << cPtr << std::endl; // 输出"Hello"

指针数组

指针数组是一组指向特定类型数据的指针。

int num1 = 1, num2 = 2, num3 = 3;
int* ptrArray[3] = {&num1, &num2, &num3}; // 指针数组,每个元素指向一个整数
std::cout << *ptrArray[0] << std::endl; // 输出1

命令行参数

在C++中,main函数可以接受两个参数,第一个是命令行参数的数量,第二个是一个指向这些参数的指针数组(字符指针数组),这些参数以NULL结束。

#include <iostream>
int main(int argc, char* argv[]) {
    for(int i = 0; i < argc; ++i) {
        std::cout << "Argument " << i << ": " << argv[i] << std::endl;
    }
    return 0;
}

函数指针数组

可以创建一个数组,其中每个元素都是指向函数的指针,这样就可以通过索引来调用不同的函数。

void func1() { std::cout << "Function 1 called" << std::endl; }
void func2() { std::cout << "Function 2 called" << std::endl; }
typedef void (*FuncPtr)(); // 函数指针类型别名
FuncPtr funcPtrArray[] = {func1, func2};
int main() {
    funcPtrArray[0](); // 调用func1
    funcPtrArray[1](); // 调用func2
}

C++中指针的灵活性和强大功能,但也强调了正确使用它们的重要性,以避免常见的编程错误。

目录
相关文章
|
6天前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
32 0
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
90 4
|
2月前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。
|
2月前
|
存储 C++
c++的指针完整教程
本文提供了一个全面的C++指针教程,包括指针的声明与初始化、访问指针指向的值、指针运算、指针与函数的关系、动态内存分配,以及不同类型指针(如一级指针、二级指针、整型指针、字符指针、数组指针、函数指针、成员指针、void指针)的介绍,还提到了不同位数机器上指针大小的差异。
62 1
|
2月前
|
存储 编译器 C语言
C++入门2——类与对象1(类的定义和this指针)
C++入门2——类与对象1(类的定义和this指针)
45 2
|
2月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
2月前
|
存储 C++ 索引
C++函数指针详解
【10月更文挑战第3天】本文介绍了C++中的函数指针概念、定义与应用。函数指针是一种指向函数的特殊指针,其类型取决于函数的返回值与参数类型。定义函数指针需指定返回类型和参数列表,如 `int (*funcPtr)(int, int);`。通过赋值函数名给指针,即可调用该函数,支持两种调用格式:`(*funcPtr)(参数)` 和 `funcPtr(参数)`。函数指针还可作为参数传递给其他函数,增强程序灵活性。此外,也可创建函数指针数组,存储多个函数指针。
|
3月前
|
编译器 C++
【C++核心】指针和引用案例详解
这篇文章详细讲解了C++中指针和引用的概念、使用场景和操作技巧,包括指针的定义、指针与数组、指针与函数的关系,以及引用的基本使用、注意事项和作为函数参数和返回值的用法。
56 3
|
2月前
|
算法 C++
【算法】双指针+二分(C/C++
【算法】双指针+二分(C/C++
|
2月前
|
存储 编译器 程序员
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(二)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值