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的值
  2. 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函数
  2. 指针函数:返回值为指针的函数。

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

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值