c++ primer 学习之路 (18)4.7 指针和*存储空间 &取地址符 *解引用 声明和初始化指针 new delect

4.7 指针和*存储空间

指针是一个变量,其存储的是值的地址,而不是值本身。我们先看一看如何找到常规变量的地址。只需对变量应用地址运算符(&),就可以获得它的位置;例如,如果home是一个变量,则&home是它的地址

程序清单4.14演示了这个运算符的用法。

程序清单4.14 address.cpp

#include<iostream>
#include<climits>
#include<string>
using namespace std;
int main()
{
 int donuts = 6;
 double cups = 4.5;
 cout << "donuts value = " << donuts;
 cout << "and donuts adress = " << &donuts << endl;
 cout << "cups value = " << cups;
 cout << "and cups adress = " << &cups << endl;
 system("pause");
 return 0;
}

c++ primer 学习之路 (18)4.7 指针和*存储空间 &amp;取地址符 *解引用 声明和初始化指针 new delect

C++采用的方法是,使用关键字new请求正确数量的内存以及使用指针来跟踪新分配的内存的位置

指针用于存储值的地址。因此,指针名表示的是地址。*运算符被称为间接值(indirect velue)或解除引用(dereferencing)运算符,将其应用于指针,可以得到该地址处存储的值(这和乘法使用的符号相同;C++根据上下文来确定所指的是乘法还是解除引用)。例如,假设manly是一个指针,则manly表示的是一个地址,而*manly表示存储在该地址处的值。*manly与常规int变量等效。程序清单4.15说明了这几点,它还演示了如何声明指针。

程序清单4.15 pointer.cpp

#include<iostream>
#include<climits>
#include<string>
using namespace std;
int main()
{
 int updates = 6;
 int * p_updates;
 p_updates = &updates;
 cout << "Value: updates = " << updates;
 cout << endl << "*p_updates = " << *p_updates << endl;
 cout << "Adresses:&updates= " << &updates << endl;
 cout << "p_updates = " << p_updates << endl;
 *p_updates = *p_updates + 1;
 cout << "Now updates = " << updates << endl;
 system("pause");
 return 0;
}

c++ primer 学习之路 (18)4.7 指针和*存储空间 &amp;取地址符 *解引用 声明和初始化指针 new delect

从中可知,int变量updates和指针变量p_updates只不过是同一枚硬币的两面。变量updates表示值,并使用&运算符来获得地址;而变量p_updates表示地址,并使用*运算符来获得值(参见图4.8)。由于p_updates指向updates,因此*p_updates和updates完全等价。可以像使用int变量那样使用*p_updates。正如程序清单4.15表明的,甚至可以将值赋给*p_updates。这样做将修改指向的值,即updates。

c++ primer 学习之路 (18)4.7 指针和*存储空间 &amp;取地址符 *解引用 声明和初始化指针 new delect

4.7.1 声明和初始化指针

c++ primer 学习之路 (18)4.7 指针和*存储空间 &amp;取地址符 *解引用 声明和初始化指针 new delect

顺便说一句,*运算符两边的空格是可选的。传统上,C程序员使用这种格式:

int *ptr;

这强调*ptr是一个int类型的值。而很多C++程序员使用这种格式:

int*  ptr;

这强调的是:int*是一种类型—指向int的指针。在哪里添加空格对于编译器来说没有任何区别

使用new来分配内存

int *pn=new int;

使用delete释放内存

c++ primer 学习之路 (18)4.7 指针和*存储空间 &amp;取地址符 *解引用 声明和初始化指针 new delect

这将释放ps指向的内存,但不会删除指针ps本身。

只能用delete来释放使用new分配的内存。然而,对空指针使用delete是安全的。

4.7.6 使用new来创建动态数组

不管程序最终是否使用数组,数组都在那里,它占用了内存。在编译时给数组分配内存被称为静态联编(static binding),意味着数组是在编译时加入到程序中的。但使用new时,如果在运行阶段需要数组,则创建它;如果不需要,则不创建。还可以在程序运行时选择数组的长度。这被称为动态联编(dynamic binding),意味着数组是在程序运行时创建的。这种数组叫作动态数组(dynamic array)。使用静态联编时,必须在编写程序时指定数组的长度;使用动态联编时,程序将在运行时确定数组的长度。

使用new创建动态数组

int * pso=new int[10];

new运算符返回第一个元素的地址。在这个例子中,该地址被赋给指针psome。

对于使用new创建的数组,应使用另一种格式的delete来释放:

delete [] pso;

  • 不要使用delete来释放不是new分配的内存。
  • 不要使用delete释放同一个内存块两次。
  • 如果使用new [ ]为数组分配内存,则应使用delete [ ]来释放。
  • 如果使用new [ ]为一个实体分配内存,则应使用delete(没有方括号)来释放。
  • 对空指针应用delete是安全的。
  • 程序清单演示了如何使用new来创建动态数组以及使用数组表示法来访问元素;它还指出了指针和真正的数组名之间的根本差别。
  • #include<iostream>
    using namespace std;
    int main()
    {
     double * p3 = new double[3];
     p3[0] = 0.2;
     p3[1] = 0.5;
     p3[2] = 0.8;
     cout << "p3[1]=" << p3[1] << endl;
     p3 = p3 + 1;
     cout << "Now p3[0] is " << p3[0] << endl;
     cout << "p3[1]" << p3[1] << endl;
     p3 = p3 - 1;
     delete [] p3;
     system("pause");
     return 0;
     
    }
    结果如下:
  • c++ primer 学习之路 (18)4.7 指针和*存储空间 &amp;取地址符 *解引用 声明和初始化指针 new delect