指针是一种用于存储对象内存地址的变量。
C 和 C++ 都大量使用指针,主要有三个原因:
对于所有这些情况,C 风格编程中使用原始指针。然而,原始指针是许多关键编程错误的原因。因此,除非它们显著提高效率并且毫无疑问哪个指针拥有对象并负责销毁它,否则强烈禁止使用它们。现代 C++ 提供 Lambda 表达式用于传递函数,智能指针用于分配对象,以及迭代器主要用于遍历数据结构。与其使用原始指针,不如使用这些语言和库特性来使你的程序更安全、更易于理解,也更易于维护。
学习 C++ 指针简单而有趣。指针有助于更快地执行一些 C++ 操作,它们对于执行其他 C++ 任务(包括动态内存分配)也非常重要。
如你所知,每个变量都是一个具有已定义地址的内存位置,可以使用 & 运算符(表示内存地址)访问该地址。
声明指针变量时,其内容未初始化。换句话说,它有一个“任何地方”的位置,这显然是一个无效地址。这很危险!指针需要通过为其分配实际地址来初始化。通常,地址运算符 (&) 用于此。
我们知道编程中的所有内容都存储在内存中,每个内存单元都包含两个实体——一个是**地址位置**,另一个是存储在其中的**值**。

地址运算符 (&) 作用于变量,返回变量的地址。例如,如果变量 number 是一个 int,则 &number 返回变量 number 的地址。
可以使用地址运算符获取变量的地址,然后将该地址分配给指针变量。
假设我们声明一个类型为 int 的变量 v,并将其初始化为值 1。
int v = 1;
值 1 将存储在地址位置,例如此处为 2000,而“v”将指向或包含值 1。下一个整数类型的值将按照上述声明在连续的内存位置分配。这表明每个变量将具有唯一的地址位置,而无论其值如何。要获取变量的地址,我们在变量前使用 & (amperand) 运算符。
&v;
请看下面给出的 C++ 程序示例,它打印定义变量的地址
#include <iostream>
using namespace std;
int main () {
int var1;
char var2[20];
cout << "Address of var1 variable will be: ";
cout << &var1 << endl;
cout << "Address of var2 variable will be: ";
cout << &var2 << endl;
return 0;
}
输出
Address of var1 variable will be: 0x7fff0fb6d57c Address of var2 variable will be: 0x7fff0fb6d560
包含另一个变量地址的变量称为指针。在使用指针之前,就像任何变量或常量一样,你应该声明它。

type *var_name;
这里,**var_name** 是指针变量的名称,而 type 是指针的基本类型;它必须是有效的 C++ 类型。你用来声明指针的相同星号也用于乘法。但是,此句中的星号表示变量是指针。
int *ip; // pointer mainly to an integer
double *dp; // pointer mainly to a double
float *fp; // pointer mainly to a float
char *ch // pointer mainly to a character
所有指针,无论它们是整数、浮点数、字符还是其他类型,实际上都具有相同的值,这是一个长的十六进制数,对应于内存地址。指针指向的变量或常量是区分不同数据类型指针的唯一主要因素。
将会非常频繁地对指针执行一些关键操作,例如
这是通过使用一元运算符 * 来实现的,该运算符返回其操作数指示的地址处变量的值。

这些操作在下面给出的示例中使用。
#include <iostream>
using namespace std;
int main () {
int var = 40; // the actual variable declaration.
int *ip; // the pointer variable
ip = &var; // store address of var in pointer variable
cout << "The Value of var variable will be: ";
cout << var << endl;
// now print the address which is stored in ip pointer variable
cout << "The Address stored in ip variable will be: ";
cout << ip << endl;
// now access the value at the address available in pointer
cout << " The Value of *ip variable will be: ";
cout << *ip << endl;
return 0;
}
输出
The value of var variable will be: 40 The address stored in ip variable will be: 0x7ffe608a7fa4 The value of *ip variable will be: 40
让我们编写另一个 C++ 程序来演示 C++ 中指针的 * 用法。
#include <iostream>
using namespace std;
int main()
{
// its a normal kind integer variable
int Var = 20;
// A pointer variable which holds address of var.
int *ptr = &Var;
// This line will mainly prints value at address which is stored in ptr.
// Value stored isthe value of variable "var"
cout << "Value of Var = "<< *ptr << endl;
cout << "Address of Var = " << ptr << endl;
// We can also use ptr as lvalue (Left hand
// side of assignment)
*ptr = 40; // Value at address is now 20
// This prints 40
cout << "After doing *ptr = 40, *ptr is "<< *ptr << endl;
return 0;
}
输出
Value of Var = 20 Address of Var = 0x7ffe7cb29f8c After doing *ptr = 40, *ptr is 40

C++ 语言广泛使用指针。
借助 C 编程语言中基于指针的 malloc() 和 calloc() 方法,我们可以动态分配内存。
在 C 语言的数组、函数和结构中,指针经常被使用。性能得到提升,同时代码量减少。
**空指针**、**指针算术**、**指针与数组**、**指针数组**、**指向指针的指针**以及**将指针传递给函数**,这些都是指针中非常重要的概念。指针有各种简单的概念,它们对于 C++ 编程非常重要。
以下是每个 C++ 程序员都应该理解的几个基本指针原则:将在后续教程中讨论。
| 序号 | 概念与描述 |
|---|---|
| 1 | 空指针
C++ 支持空指针。空指针是那些已分配 NULL 的指针。 |
| 2 | 指针算术
你可以像对数值一样对指针执行算术运算:++、--、+、- |
| 3 | 指针与数组
指针和数组之间有着深刻的联系。 |
| 4 | 指针数组
你可以定义数组来保存多个指针。 |
| 5 | 指向指针的指针
C++ 允许你拥有指向指针的指针,依此类推。 |
| 6 | 将指针传递给函数
通过引用或地址传递参数使被调用函数能够在调用函数中更改传递的参数。 |
| 7 | 从函数返回指针
C++ 允许函数返回指向局部变量、静态变量以及动态分配内存的指针。 |
指向指针的指针被认为是多重间接寻址的一种类型,或者只是一串指针。指针通常包含变量的地址。在指向指针的指针的定义中,第一个指针包含第二个指针的地址,这标识了真实值所在的位置,如下图所示。
指向指针的变量必须这样描述。在其名称前添加一个额外的星号以表示此。例如,声明一个指向 int 类型指针的指针的声明如下:
int **var;
当通过指向指针的指针间接指向目标值时,必须使用两次星号运算符才能访问目标值,如下例所示。
#include <iostream>
using namespace std;
int main () {
int var;
int *ptr;
int **pptr;
var = 5000;
// take the address of var
ptr = &var;
// using address of operator & take the address of ptr
pptr = &ptr;
// using pptr take the value
cout << "The value of var :" << var << endl;
cout << "The value is available at *ptr :" << *ptr << endl;
cout << "The Value is available at **pptr :" << **pptr << endl;
return 0;
}
输出
The value of var :5000 The value is available at *ptr :5000 The Value is available at **pptr :5000
指针可以传递给 C++ 中的函数。为此,只需将函数参数声明为指针类型即可。
让我们使用一个非常简单的 C++ 程序作为将无符号长整型指针传递给函数并在其中更改值以在调用函数中反映的示例。
#include <iostream>
#include <ctime>
using namespace std;
void getSeconds(unsigned long *par);
int main () {
unsigned long sec;
getSeconds( &sec );
// print the actual value
cout << "Number of seconds will be:" << sec << endl;
return 0;
}
void getSeconds(unsigned long *par) {
// get the current number of seconds
*par = time( NULL );
return;
}
输出
Number of seconds will be:1660158812
现在让我们看一个函数示例,该函数可以接受指针,也可以接受数组
#include <iostream>
using namespace std;
// function declaration:
double getAverage(int *arr, int size);
int main () {
// an int array with 6 elements.
int balance[5] = {1000, 20000, 3000, 1700, 5200};
double avg;
// now pass the pointer to the array as an argument.
avg = getAverage( balance, 6 ) ;
// output the returned value
cout << "Average value is will be: " << avg << endl;
return 0;
}
double getAverage(int *arr, int size) {
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
avg = double(sum) / size;
return avg;
}
输出
Average value is will be: 10610.7
类似于 C++ 允许你从函数返回数组(如我们之前在某个主题中看到的那样),C++ 也允许你从函数返回指针。你需要声明一个返回指针的函数,如下例所示:
int * myFunction() {
.
.
.
}
第二件要记住的事情是,将局部变量的地址返回到函数外部不是一个明智的做法,因此你应该将局部变量定义为静态变量。
现在请看下面的代码,它将生成 10 个随机整数并使用主要表示指针的数组名(即第一个数组元素的地址)返回它们。
#include <iostream>
#include <ctime>
using namespace std;
// function mainly to generate as well as to retrun random numbers.
int * getRandom( ) {
static int r[12];
// set the seed
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 12; ++i) {
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// main function to call above defined function.
int main () {
// a pointer to an int.
int *p;
p = getRandom();
for ( int i = 0; i < 12; i++ ) {
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}
输出
1238517784 1706475627 84960591 958048303 73893020 158631104 477142828 2116082795 832547651 1809736359 615981633 938663983 *(p + 0) : 1238517784 *(p + 1) : 1706475627 *(p + 2) : 84960591 *(p + 3) : 958048303 *(p + 4) : 73893020 *(p + 5) : 158631104 *(p + 6) : 477142828 *(p + 7) : 2116082795 *(p + 8) : 832547651 *(p + 9) : 1809736359 *(p + 10) : 615981633 *(p + 11) : 938663983