009 C++的原始指针(Raw Pointer)


作者Lou Xiao, deepseek创建时间2025-04-02 07:14:51更新时间2025-04-02 07:14:51

1. 原始指针基本概念

原始指针是C++中最基础的指针类型,直接存储内存地址。它们提供底层内存操作能力,但也需要开发者自行管理生命周期。

1.1 指针声明语法

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 T* ptr; // 指向类型T的指针
2 const T* ptr; // 指向const T的指针
3 T* const ptr; // const指针(不可修改地址)

2. 指针基本操作

2.1 取地址与解引用

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 int value = 42;
2 int* ptr = &value; // 取地址
3 *ptr = 100; // 解引用并修改

2.2 指针算术运算

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 int arr[5] = {1,2,3,4,5};
2 int* p = arr;
3 p++; // 指向arr[1]
4 p += 2; // 指向arr[3]

2.3 指针比较

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 if (ptr1 == ptr2) {...}
2 if (ptr != nullptr) {...}

3. 指针与数组

3.1 数组名退化

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 int arr[3] = {1,2,3};
2 int* p = arr; // 数组名退化为指针

3.2 指针遍历数组

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 for (int* p = arr; p != arr + 3; ++p) {
2 std::cout << *p << " ";
3 }

4. 多级指针

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 int value = 42;
2 int* p = &value;
3 int** pp = &p; // 二级指针
4 int*** ppp = &pp; // 三级指针

5. 指针与const

5.1 组合形式

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 const int* p1; // 指向const int的指针
2 int const* p2; // 同上,等价写法
3 int* const p3; // const指针,指向int
4 const int* const p4; // const指针,指向const int

5.2 类型转换

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 const int* p1 = &value;
2 int* p2 = const_cast<int*>(p1); // 去除const限定

6. 函数与指针

6.1 指针参数

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 void modify(int* ptr) {
2 *ptr = 100;
3 }

6.2 指针返回值

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 int* create_array(size_t size) {
2 return new int[size];
3 }

6.3 函数指针

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 void (*funcPtr)(int) = &myFunction;
2 funcPtr(42);

7. 动态内存管理

7.1 new/delete

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 int* p = new int(42); // 单个对象
2 delete p;
3
4 int* arr = new int[10]; // 数组
5 delete[] arr;

7.2 malloc/free

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 int* p = (int*)malloc(sizeof(int));
2 free(p);

8. 指针安全问题

8.1 常见问题

  • 空指针解引用
  • 野指针(Dangling pointer)
  • 内存泄漏
  • 双重释放
  • 数组越界

8.2 防御性编程

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 if (ptr != nullptr) {
2 *ptr = value;
3 }
4
5 // 使用RAII管理资源
6 class PointerWrapper {
7 T* ptr;
8 public:
9 explicit PointerWrapper(T* p) : ptr(p) {}
10 ~PointerWrapper() { delete ptr; }
11 };

9. 指针与类型转换

9.1 C风格转换

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 void* vp = ...;
2 int* ip = (int*)vp;

9.2 C++风格转换

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 const int* cip = ...;
2 int* ip = const_cast<int*>(cip);
3
4 Base* b = ...;
5 Derived* d = dynamic_cast<Derived*>(b);

10. 指针最佳实践

  1. 优先使用智能指针:unique_ptr/shared_ptr
  2. 明确指针所有权:文档说明指针所有权关系
  3. 避免裸new/delete:使用RAII包装器
  4. 检查nullptr:在使用前验证指针有效性
  5. 限制指针作用域:尽量缩小指针可见范围
  6. 使用引用替代:当不需要nullptr或重指向时

11. 现代C++替代方案

11.1 智能指针

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 std::unique_ptr<int> up(new int(42));
2 std::shared_ptr<int> sp = std::make_shared<int>(42);

11.2 引用

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 void process(const std::string& str); // 优先使用const引用

11.3 容器与视图

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 std::vector<int> vec{1,2,3};
2 std::span<int> sp(vec); // C++20

12. 指针性能考量

  1. 内存访问开销:指针解引用比直接访问慢
  2. 缓存友好性:连续内存访问效率更高
  3. 别名分析影响:指针可能限制编译器优化
  4. 虚函数调用:通过指针的虚函数调用有额外开销

13. 特殊指针类型

13.1 void指针

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 void* vp = ...;
2 // 必须转换为具体类型后才能使用

13.2 函数指针

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 using Handler = void(*)(int);
2 Handler h = &myHandler;

13.3 成员指针

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 struct S { int value; };
2 int S::* ptr = &S::value;
3 S s;
4 s.*ptr = 42;

14. 指针与多态

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 class Base { virtual void foo(); };
2 class Derived : public Base {};
3
4 Base* b = new Derived();
5 b->foo(); // 多态调用
6 delete b;

15. 指针调试技巧

  1. 使用调试器:检查指针值和指向内容
  2. 标记特殊值:如0xDEADBEEF标记已释放内存
  3. 边界检查工具:AddressSanitizer等
  4. 日志记录:重要指针操作添加日志

16. 总结

原始指针是C++强大但危险的特征:
- 提供底层内存控制能力
- 需要开发者自行管理生命周期
- 容易引入各种内存错误
- 在现代C++中应谨慎使用

最佳实践:
- 新代码优先使用智能指针和引用
- 必须使用时严格遵循资源管理规范
- 添加充分注释说明指针所有权
- 使用静态分析工具检查指针使用

文章目录