IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> cpp中指针和自由存储空间 -> 正文阅读

[C++知识库]cpp中指针和自由存储空间

????????计算机程序在存储数据时必须跟踪的3种基本属性,信息存储在何处,存储的值为多少,存储的信息是什么类型。定义一个简单变量,声明语句指出了值的类型和符号名,还让程序为值分配内存,并在内部跟踪该内存单元。指针是一个变量,其存储的是值的地址,而不是值本身。常规变量,只需对变量应用地址运算符&,就可以获得它的位置,使用常规变量时,值是指定的量,地址为派生量。

1.指针与cpp基本原理

? ? ? ? 考虑为数组分配内存的情况,传统的方法是声明一个数组,要在cpp中声明数组,必须指定数组的长度。因此,数组长度在程序编译时就设定好了,这就是编译阶段决策,cpp采用的方法是使用关键字new请求正确数量的内存以及使用指针来跟踪新分配的内存的位置。处理存储数据,将地址视为指定的量,而将值视为派生量。一种特殊类型的变量—指针用于存储值的地址。因此,指针名表示的是地址,*运算符被称为间接值或解除引用运算符,将其应用于指针。可以得到该地址处存储的值,例如,假设manly是一个指针,则manly表示的是一个地址,*manly表示存储在该地址处的值,*manly与常规int变量等效。

#include <iostream>
int main()
{
    using namespace std;
    int updates = 6;        // declare a variable
    int * p_updates;        // declare pointer to an int

    p_updates = &updates;   // assign address of int to pointer

// express values two ways
    cout << "Values: updates = " << updates;
    cout << ", *p_updates = " << *p_updates << endl;

// express address two ways
    cout << "Addresses: &updates = " << &updates;
    cout << ", p_updates = " << p_updates << endl;

// use pointer to change value
    *p_updates = *p_updates + 1;
    cout << "Now updates = " << updates << endl;
    // cin.get();
    return 0; 
}

int变量updates和指针变量p_updates只不过是同一枚硬币的两面。变量updates表示值,并使用&运算符来获得地址,而变量p_updates表示地址,并使用*运算符来获取值,由于p_updates指向updates,因此*p_updates和updates完全等价。可以像使用int变量那样使用*p_updates。

2.声明和初始化指针

? ? ? ? 需要跟踪指针指向的值的类型。

int * p_updates;

这表明,*p_updates的类型为int。由于*运算符被用于指针,因此p_update变量本身必须是指针。p_updates指向int类型,p_updates的类型是指向int的指针,或int*。p_updates是指针(地址),而*p_updates是int,而不是指针。顺便说一句,*运算符两边的空格是可选的,传统上,C程序员使用这种格式:

int *ptr;

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

int* ptr;

int* 是一种类型—执行int的指针,在哪里添加空格对于编译器来说没有任何区别,甚至可以这么做

int*ptr;

但是,下面的声明创建一个指针(p1)和一个int变量(p2):

int* p1,p2;

对每个指针变量名,都需要使用一个*。在cpp中,int*是一种复合类型,是指向int的指针。

可以用同样的句法来声明指向其他类型的指针:

double * tax_ptr;
char * str;

由于已将tax_ptr声明为一个指向double的指针,因此编译器知道*tax_ptr是一个double类型的值。*tax_ptr是一个以浮点格式存储的值,这个值占据8个字节。指针变量不仅仅是指针,而且指向特定类型的指针。tax_ptr的类型是指向double的指针(或double*类型),str是指向char的指针类型(或char*)。尽管它们都是指针,却是不同类型的指针,和数组一样,指针都是基于其他类型的。

? ? ? ? 虽然tax_ptr和str指向两种长度不同的数据类型,但这两个变量本身的长度通常是相同的。也就是说,char的地址与double的地址的长度相同。地址的长度或值既不能指示关于变量的长度或类型的任何信息,一般,地址需要2个还是4个字节,取决于计算机系统。

? ? ? ? 可以在声明语句中初始化指针。在这种情况下,被初始化的是指针,而不是它指向的值。也就说,将pt(而不是*pt)的值设置为&higgens。

int higgens = 5;
int *pt = &higgens;

3.指针和数字

? ? ? ? 指针不是整型,虽然计算机通常把地址当成整数来处理。从概念上看,指针与整数是截然不同的类型。整数是可以执行加减除等运算的数字,而指针描述的是位置 ,将两个地址相乘没有任何意义,不能简单的将整数赋给指针:

int *pt;
pt = 0xB8000000;

在这里,左边是指向int的指针,因此可以把它赋给地址,但右边是一个整数,编译器将显示一条错误消息,通告类型不匹配,要将数字值作为地址来使用,应通过强制类型转换将数字转换为适当的地址类型:

int *pt;
pt = (int*)0xB8000000;

4.使用new来分配内存

? ? ? ? 将指针初始化为变量的地址,变量是在编译时分配的有名称的内存,而指针只是为可以通过名称直接访问的内存提供了一个别名。指针真正的用武之地在于,在运行阶段分配未命名的内存以存储值,在这种情况下,只能通过指针来访问内存。在c中,可以用库函数malloc()来分配内存;在cpp中可以用new运算符。

? ? ? ? 在运行阶段为一个int值分配未命名的内存,并使用指针来访问这个值。这里的关键所在是cpp中的new运算符,new将找到一个长度正确的内存块,并返回该内存块的地址

int * pn = new int;

? ? ? ? new int需要适合存储int的内存,new运算符根据类型来确定需要多少字节的内存。然后找到这样的内存并返回其地址。将地址赋给pn,pn是被声明为指向int的指针,现在pn是地址,而*pn是存储在那里的值。

int higgens;
int * pt = &higgens;

? ? ? ? 在这两种情况(pn和pt)下,都是将一个int变量的地址赋给指针。在第二种情况下,可以通过名称higgens来访问该int,在第一种情况下,则只能通过该指针进行访问。这引出了一个问题:pn指向的内存没有名称,pn指向一个数据对象,数据对象指的是为数据项分配的内存块,变量也是数据对象,但pn指向的内存不是变量。

? ? ? ? 对于指针,需要指出的另一点是,new分配的内存块通常与常规变量声明分配的内存块不同。变量nights和pd的值都存储在被称为栈的内存区域中,而new从被称为堆或自由存储区的内存区域分配内存。

5.使用delete释放内存

????????delete运算符,在使用完内存后,能够将其归还给内存池,归还或释放(free)的内存可供程序的其他部分使用。 使用delete时,后面要加上指向内存块的指针。

int * ps=new int;
delete ps;

6.使用new来创建动态数组

? ? ? ? 对于大型数组(如数组、字符串和结构),应使用new,如果通过声明来创建数组,则在程序被编译时为它分配内存空间。在编译时给数组分配内存被称为静态联编,意味着数组是在编译时加入到程序中的,在使用new时,如果在运行阶段需要数组,则创建它;还可以在程序运行时选择数组的长度,这被称为动态联编,意味着数组是在程序运行时创建的。这种数组叫做动态数组,使用静态联编时,必须在编写程序时指定数组的长度,使用动态联编时,程序将在运行时确定数组的程度。

6.1 使用new创建动态数组

? ? ? ? 在cpp中,创建动态数组很容易,只要将数组的元素类型和元素数目告知new即可。必须在类型名后加上方括号,其中包括包含元素数目,例如,要创建一个包含10个int元素的数组,

int * psome = new int[10];

new运算符返回第一个元素的地址。该地址被赋给指针平some。当程序使用完new分配的内存块时,应使用delete释放它们。对于使用new创建的数组,应使用另一种格式的delete来释放。

delete [] psome;

方括号告诉程序,应释放整个数组,而不仅仅是指针指向的元素,请注意delete和指针之间的方括号,如果使用new时,不带方括号,则使用delete时,也不应带方括号,如果使用new时带方括号,则使用delete时也应带方括号。

6.2 使用动态数组

? ? ? ? 创建指针psome,它指向包含10个int值的内存块中的第一个元素:

int * psome = new int[10];

? ? ? ? 如何访问其中的元素呢?由于psome指向数组的第一个元素,因此*psome是第一个元素的值。这样,还有9个元素,只要把指针当做数组名使用即可。也就是说对于第一个元素,可以使用psome[0],而不是*psome;对于第二个元素,可以使用psome[1],以此类推,这样使用指针来访问动态数组就非常简单,可以这么做的原因是,c和cpp内部都使用指针来处理数组。

#include <iostream>
int main()
{
    using namespace std;
    double * p3 = new double [3]; // space for 3 doubles
    p3[0] = 0.2;                  // treat p3 like an array name
    p3[1] = 0.5;
    p3[2] = 0.8;
    cout << "p3[1] is " << p3[1] << ".\n";
    p3 = p3 + 1;                  // increment the pointer
    cout << "Now p3[0] is " << p3[0] << " and ";
    cout << "p3[1] is " << p3[1] << ".\n";
    p3 = p3 - 1;                  // point back to beginning
    delete [] p3;                 // free the memory
    // cin.get();
    return 0; 
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-12 17:14:26  更:2022-03-12 17:15:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:00:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码