C++ 查漏补缺

指针的退化及如何避免

在C++中,”指针退化”是指当数组作为函数参数传递时,它会”退化”为指向第一个元素的指针。这是因为在C++中,数组并不知道它们自己的大小,所以当你把一个数组作为参数传递给一个函数时,函数并不知道这个数组的大小,只知道它的起始地址。

例如,假设你有一个函数void foo(int arr[]),当你传递一个数组给这个函数时,例如int arr[10]; foo(arr);,函数foo实际上看到的是一个指向arr的第一个元素的指针,而不是整个数组。

要防止指针退化,有几种方法:

  1. 使用标准库容器,如std::vectorstd::array。这些容器知道它们自己的大小,因此不会发生指针退化。例如: void foo(std::vector<int>& arr)

  2. 使用模板函数,使函数可以接受数组的引用,并且能够保留数组的大小信息。例如: template<size_t N> void foo(int (&arr)[N])

  3. 传递数组的大小作为另一个参数。例如: void foo(int* arr, size_t size)。这样,即使数组退化为指针,函数仍然可以知道数组的大小。

引用与指针的区别

在C++中,指针和引用都可以用于间接引用其他对象。然而,它们在语法和行为上有一些关键的不同:

  1. 初始化:引用在创建时需要初始化,并且一旦初始化后就不能改变引用的目标,也就是说它始终引用最初赋给它的对象。而指针可以在任何时间指向任何对象或者NULL。

  2. 空值:指针可以为NULL,表示它不指向任何对象。而引用必须始终引用一个有效的对象,不能有NULL引用。

  3. 间接访问:使用指针时,需要使用解引用运算符(*)来访问它指向的对象,而引用则可以像普通变量那样直接使用。

  4. 支持的操作:指针支持更多的操作,例如指针算术(即增加或减少指针的值,以指向内存中的不同位置)。引用则不能进行这种操作。

  5. 内存占用:引用实际上并不占用任何内存,它只是一个别名。而指针是一个实际的变量,它占用内存空间并存储一个地址值。

    但引用在程序中并不是不占用任何字节,引用本质上就是一个常量指针(constant pointer)。它在内存中占据的空间和指针一样,通常是 4 字节(在 32 位系统)或 8 字节(在 64 位系统)。然而,引用本身并不存储任何值,它只是一个别名,代表它引用的对象。在某些优化的情况下,如果引用没有被用作一个对象的别名(也就是说,它被直接用于访问该对象),编译器可能会优化掉引用,使其不占用任何内存空间。但是,这种优化并不是在所有情况下都会发生。所以,说引用不占用内存空间并不完全准确,实际情况取决于编译器的优化和引用的使用方式。

总的来说,引用在某些情况下可以提供更简洁的语法,而指针则提供了更大的灵活性和控制能力。选择使用哪一个取决于具体的编程需求。

版权声明: 如无特别声明,本文版权归 Mr Chen 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:《 温故而知新之-C++ 》

本文链接:https://gbcpp.github.io/notes/learning-cpp-notes.html

本文最后一次更新为 天前,文章中的某些内容可能已过时!