C++基础总结(4)-----指针

指针是一个变量,其存储的值是地址,而不是值本身。(有点类似于组成原理里面的变址寻址)

在讨论指针之前,我们先来看看如何寻找常规变量的地址。只需对变量引用取地址符(&)就行了。

如下面一段代码:

#include <iostream>

using namespace std;

int main()
{
    int dounts=6;
    double cpus=5.6;

    cout<<"dounts = "<<dounts<<", address is "<<&dounts<<endl;
    cout<<"cpus = "<<cpus<<", address is "<<&cpus<<endl;
    return 0;
}

*运算符被称为间接值或者解除引用运算符。将其用于指针,便可以得到该地址存储的值。


duck变量为int型变量,其分配的地址是1000,里面存储的值是12,而birding是一个int型指针变量它本身的地址是1006,而在它里面存储的值duck的地址1000。

所谓指针指的是存储的其他变量的地址。


指针的声明和初始化

int *ptr;//声明一个int型指针

*两边的空格是可选的。

传统上,C程序员使用这种格式。

int *ptr;//强调*ptr是一个int类型

C++程序员通常使用下面这种方式

int* ptr;

强调int*之一中指向int类型的指针。在哪里添加空格对于编译器没有区别。

注意:

int *p1, p2;表示的是创建一个int类型指针p1和一个变量p2。如果要声明两个变量,应该这样做:int *p1, *p2。


指针的初始化

#include <iostream>

using namespace std;

int main()
{
    int a=3;
    int *b;
    b=&a;

    cout<<"a = "<<a<<" at "<<&a<<endl;//&a表示a的地址
    cout<<"*b = "<<*b<<endl;//<span style="font-family: Arial, Helvetica, sans-serif;">*b 表示b里面存储的地址所指向的位置存储的值,即a的值</span>
    cout<<"the value of b is "<< b<<" at "<<&b<<endl;//b表示的是b里面存储的值,即a的地址
    return 0;
}



从运行结果可以证明上面的图的正确性。

注意:C++在创建指针的时候,计算机将会分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。

如下所示:

         int *a;

         *a=2333;

上面这段代码并没有为2333分配内存,而是将其随机存放在一个位置,有可能是空闲位置,有可能是一个已经存放了数据的位置从而造成数据损坏。


使用new申请内存

  int * pn=new int;

new int 告诉计算机程序要申请一块int类型的内存,new运算符根据类型判断需要多少字节的内存。找到内存之后将地址传回pn。

还可以使用变量直接赋值。

  int higgens;

  int * pt=&higgens;

申请数组

以申请int类型的数组为例:

  int * psome=new int[20];//执行这句的时候,计算机会申请10个int型的连续存储内存,并将首地址返回。


#include <iostream>

using namespace std;

int main()
{
    int nights = 1001;
    int * pt = new int; //C-style
    *pt = 1001;

    cout << nights << ",location " << &nights << endl;
    cout << "int value " << (*pt) << "location " << pt << endl;

    double * pd=new double;
    *pd = 10001;

    cout << "value = " << *pd << " location " << pd << endl; //show the location of pd;
    cout << "location of pointer pd " << &pd << endl;
    cout << "size of pt " << sizeof(pt) << endl;//显示申请的地址的大小
    cout << "sizeof *pt " << sizeof(*pt) << endl;//显示存储的地址里面的值的大小
    cout << "size of pd " << sizeof(pd) << endl;
    cout << "size of *pd " << sizeof(*pd) << endl;

    /*
    不初始化的话pp里面存的就是未知地址,可能会造成数据损坏、
    */
    double *pp;
    cout<<"pp at "<<&pp<<endl;

 //   *pp=3;  //错误的用法
  //  cout<<pp<<endl;

    pp=new double();
    cout<<"*pp at "<<pp<<endl;
    return 0;
}



一半常规变量申请的内存是在栈中的,随着函数的生命周期的结束会自动被回收。但是new申请的内存在堆(heap)或自由存储区中,用完之后必须被回收。不然会造成内存的泄露。所以这里我们需要使用delete来回收new申请的内存。

delete的用法

int *ps=new int;
delete ps;
int jugs=5;
int *pi=&jugs;
delete pi;//wrong
delete只能用来回收new申请的动态内存,所以第二种用法无效。

删除数组的用法和上面的类似

int *a=new int[10];
delete []a;


使用new和delete的规则

1.delete只能用来释放new分配的内存

2.不要使用delete对同一个内存释放两次

3.new和delete应该成对出现。

4.对空指针使用delete是安全的。


delete删除的是new申请的内存里面的值,而不是指针本身。

#include<iostream>

using namespace std;

int main()
{
    int a=3;
    int *b=&a;
    int *c=new int();
    int *d=c;

    *c=123;
    cout<<"a = "<<a<<", the address of a is "<<&a<<endl;
    cout<<*b<<" at "<<b<<",the address of b is "<<&b<<endl;
    cout<<"*c = "<<*c<<",the address stored in c is "<<c<<" and the address of c is "<<&c<<endl;
    cout<<"*d = "<<*d<<",and the address stored in d is "<<d<<",the address of d is "<<&d<<endl;
    delete c;//回收内存
    //delete d; 加上之后影响不大
    cout<<*c<<",the address in c is "<<c<<",and c's address is "<<&c<<endl;
     cout<<*d<<",the address in c is "<<d<<",and c's address is "<<&d<<endl;
    return 0;
}



从上面的例子可以看出指针c和d是两个不同的指针,但是他们指向的同一块内存。delete删除的只是申请的内存里面的值,而对指针本身的地址以及指针存储的地址并没有影响。系统会为a,b,c,d都分配一个地址,但是b存储的是a的地址,c,d存储的是123在堆里面的地址。delete也就是将123莫抹去,是该块内存显示为未用。





原文地址:https://www.cnblogs.com/gaot/p/7709701.html