概念定义
- 指针:
- 指针是一个变量,其存储的值是另一个变量的内存地址。例如,
int *p;
声明了一个名为p
的指针,它可以指向一个int
类型的变量。通过&
运算符可以获取变量的地址,例如int a = 10; int *p = &a;
,这里p
就指向了变量a
。
- 指针是一个变量,其存储的值是另一个变量的内存地址。例如,
- 引用:
- 引用是一个别名,它是一个变量的另一个名字。在声明引用时,必须同时初始化它,并且之后不能再让它引用其他变量。例如,
int a = 10; int &r = a;
,r
就是a
的引用,对r
的操作就是对a
的操作。
- 引用是一个别名,它是一个变量的另一个名字。在声明引用时,必须同时初始化它,并且之后不能再让它引用其他变量。例如,
- 指针:
内存分配
- 指针:
- 指针本身需要占用内存空间来存储它所指向变量的地址。在32位系统中,指针变量通常占用4个字节,在64位系统中通常占用8个字节。例如,
int *p;
这个指针变量本身在内存中有自己的存储位置,大小为上述系统对应的字节数。
- 指针本身需要占用内存空间来存储它所指向变量的地址。在32位系统中,指针变量通常占用4个字节,在64位系统中通常占用8个字节。例如,
- 引用:
- 引用不占用额外的内存空间(从用户角度看)。引用只是变量的别名,它和被引用的变量共享相同的内存地址,编译器会在内部进行处理,使得对引用的操作直接作用于被引用的变量。
- 指针:
初始化要求
- 指针:
- 指针可以先声明,然后在后续的代码中再进行初始化。例如:
int *p; int a = 10; p = &a;
- 也可以在声明时初始化,如
int a = 10; int *p = &a;
。而且指针还可以被赋值为nullptr
(C++ 11引入)来表示它不指向任何有效的内存地址,例如int *p = nullptr;
。
- 指针可以先声明,然后在后续的代码中再进行初始化。例如:
- 引用:
- 引用必须在声明时就进行初始化,并且一旦初始化后就不能再引用其他变量。例如:
int a = 10; int &r = a; // 以下代码是错误的,不能让r再引用其他变量 // int b = 20; // r = b;
- 引用必须在声明时就进行初始化,并且一旦初始化后就不能再引用其他变量。例如:
- 指针:
使用语法和操作方式
- 指针:
- 使用指针访问所指向的变量需要使用解引用运算符
*
。例如,int a = 10; int *p = &a; *p = 20;
,这里*p
就是解引用p
,使得可以修改p
所指向的变量a
的值。 - 指针可以进行算术运算(在数组操作中比较常见)。例如,对于一个指向数组元素的指针,可以通过指针加1来指向下一个数组元素。如果
int arr[]={1,2,3}; int *p = &arr[0]; p++;
此时p
就指向了arr[1]
。
- 使用指针访问所指向的变量需要使用解引用运算符
- 引用:
- 引用的使用就像使用普通变量一样,不需要额外的运算符。例如,
int a = 10; int &r = a; r = 20;
这里直接对r
进行操作就等同于对a
进行操作。 - 引用不能进行像指针那样的算术运算,因为它不是存储地址的变量,而是一个别名。
- 引用的使用就像使用普通变量一样,不需要额外的运算符。例如,
- 指针:
作为函数参数的区别
- 指针:
- 当指针作为函数参数时,可以通过传递
nullptr
来表示一种特殊情况。例如:void func(int *p) { if (p == nullptr) { // 处理指针为空的情况 } else { // 正常处理 } }
- 函数内部可以通过修改指针的值来改变它所指向的对象。例如,在动态内存分配函数中,指针参数可以被重新赋值来指向新分配的内存块。
- 当指针作为函数参数时,可以通过传递
- 引用:
- 引用作为函数参数时,函数内部对引用的操作就是对实参本身的操作。而且引用参数在函数调用时必须提供合法的变量作为实参,不能传递类似
nullptr
这样的值,因为引用不能为空。例如:void func(int &r) { r++; } int main() { int a = 10; func(a); // 此时a的值变为11 return 0; }
- 引用作为函数参数时,函数内部对引用的操作就是对实参本身的操作。而且引用参数在函数调用时必须提供合法的变量作为实参,不能传递类似
- 指针: