指针与引用
指针基础
指针是存储内存地址的变量,是C++中最强大的特性之一。通过指针,我们可以直接操作内存,实现高效的程序设计。
// 指针基础示例
int number = 42;
int* ptr = &number; // ptr指向number的地址
std::cout << "number的值:" << number << std::endl;
std::cout << "number的地址:" << &number << std::endl;
std::cout << "ptr的值(地址):" << ptr << std::endl;
std::cout << "*ptr的值:" << *ptr << std::endl; // 解引用
int number = 42;
int* ptr = &number; // ptr指向number的地址
std::cout << "number的值:" << number << std::endl;
std::cout << "number的地址:" << &number << std::endl;
std::cout << "ptr的值(地址):" << ptr << std::endl;
std::cout << "*ptr的值:" << *ptr << std::endl; // 解引用
指针运算
指针可以进行算术运算,主要用于数组遍历和动态内存管理。
// 指针运算示例
int arr[] = {10, 20, 30, 40, 50};
int* ptr = arr; // 指向数组首元素
std::cout << "第一个元素:" << *ptr << std::endl;
ptr++; // 指针移动到下一个元素
std::cout << "第二个元素:" << *ptr << std::endl;
// 使用指针遍历数组
for (int* p = arr; p < arr + 5; p++) {
std::cout << *p << " ";
}
std::cout << std::endl;
int arr[] = {10, 20, 30, 40, 50};
int* ptr = arr; // 指向数组首元素
std::cout << "第一个元素:" << *ptr << std::endl;
ptr++; // 指针移动到下一个元素
std::cout << "第二个元素:" << *ptr << std::endl;
// 使用指针遍历数组
for (int* p = arr; p < arr + 5; p++) {
std::cout << *p << " ";
}
std::cout << std::endl;
指针与数组
数组名在大多数情况下会退化为指向首元素的指针,这使得指针和数组有密切的关系。
// 指针与数组的关系
int arr[] = {1, 2, 3, 4, 5};
int* ptr = arr;
// 数组下标访问 vs 指针访问
std::cout << "arr[2] = " << arr[2] << std::endl;
std::cout << "*(ptr + 2) = " << *(ptr + 2) << std::endl;
std::cout << "*(arr + 2) = " << *(arr + 2) << std::endl;
// 指针下标访问
std::cout << "ptr[2] = " << ptr[2] << std::endl;
int arr[] = {1, 2, 3, 4, 5};
int* ptr = arr;
// 数组下标访问 vs 指针访问
std::cout << "arr[2] = " << arr[2] << std::endl;
std::cout << "*(ptr + 2) = " << *(ptr + 2) << std::endl;
std::cout << "*(arr + 2) = " << *(arr + 2) << std::endl;
// 指针下标访问
std::cout << "ptr[2] = " << ptr[2] << std::endl;
动态内存分配
使用new和delete运算符进行动态内存分配,这是C++内存管理的重要部分。
// 动态内存分配示例
// 分配单个变量
int* ptr1 = new int;
*ptr1 = 100;
std::cout << "*ptr1 = " << *ptr1 << std::endl;
delete ptr1; // 释放内存
// 分配数组
int* ptr2 = new int[5];
for (int i = 0; i < 5; i++) {
ptr2[i] = i * 10;
}
delete[] ptr2; // 释放数组内存
// 分配单个变量
int* ptr1 = new int;
*ptr1 = 100;
std::cout << "*ptr1 = " << *ptr1 << std::endl;
delete ptr1; // 释放内存
// 分配数组
int* ptr2 = new int[5];
for (int i = 0; i < 5; i++) {
ptr2[i] = i * 10;
}
delete[] ptr2; // 释放数组内存
引用基础
引用是变量的别名,必须在声明时初始化,一旦初始化就不能改变指向。
// 引用基础示例
int number = 42;
int& ref = number; // ref是number的引用
std::cout << "number = " << number << std::endl;
std::cout << "ref = " << ref << std::endl;
ref = 100; // 修改ref也会修改number
std::cout << "修改后:" << std::endl;
std::cout << "number = " << number << std::endl;
std::cout << "ref = " << ref << std::endl;
int number = 42;
int& ref = number; // ref是number的引用
std::cout << "number = " << number << std::endl;
std::cout << "ref = " << ref << std::endl;
ref = 100; // 修改ref也会修改number
std::cout << "修改后:" << std::endl;
std::cout << "number = " << number << std::endl;
std::cout << "ref = " << ref << std::endl;
指针与引用的区别
- 初始化:指针可以不初始化,引用必须初始化
- 重新赋值:指针可以重新赋值指向其他对象,引用不能
- 空值:指针可以为nullptr,引用不能为空
- 内存占用:指针占用内存存储地址,引用通常不占用额外内存
- 使用场景:指针更灵活,引用更安全直观
常量指针与指针常量
理解const关键字与指针的结合使用。
// 常量指针:指针指向的值不能修改
const int* ptr1 = &number;
// *ptr1 = 50; // 错误:不能修改指向的值
ptr1 = &anotherNumber; // 可以改变指向
// 指针常量:指针本身不能修改
int* const ptr2 = &number;
*ptr2 = 50; // 可以修改指向的值
// ptr2 = &anotherNumber; // 错误:不能改变指向
// 常量指针常量:都不能修改
const int* const ptr3 = &number;
// *ptr3 = 50; // 错误
// ptr3 = &anotherNumber; // 错误
const int* ptr1 = &number;
// *ptr1 = 50; // 错误:不能修改指向的值
ptr1 = &anotherNumber; // 可以改变指向
// 指针常量:指针本身不能修改
int* const ptr2 = &number;
*ptr2 = 50; // 可以修改指向的值
// ptr2 = &anotherNumber; // 错误:不能改变指向
// 常量指针常量:都不能修改
const int* const ptr3 = &number;
// *ptr3 = 50; // 错误
// ptr3 = &anotherNumber; // 错误
智能指针
C++11引入了智能指针,自动管理内存,避免内存泄漏。
#include <memory>
// unique_ptr:独占所有权
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
std::cout << "*ptr1 = " << *ptr1 << std::endl;
// shared_ptr:共享所有权
std::shared_ptr<int> ptr2 = std::make_shared<int>(100);
std::shared_ptr<int> ptr3 = ptr2; // 共享所有权
std::cout << "引用计数:" << ptr2.use_count() << std::endl;
// unique_ptr:独占所有权
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
std::cout << "*ptr1 = " << *ptr1 << std::endl;
// shared_ptr:共享所有权
std::shared_ptr<int> ptr2 = std::make_shared<int>(100);
std::shared_ptr<int> ptr3 = ptr2; // 共享所有权
std::cout << "引用计数:" << ptr2.use_count() << std::endl;
学习建议
- 理解指针和引用的本质区别
- 注意动态内存分配后的释放
- 避免悬空指针和内存泄漏
- 优先使用引用而不是指针(在适用的情况下)
- 现代C++中优先使用智能指针