您的位置:首页 > 编程语言 > C语言/C++

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

2016-03-03 10:15 435 查看
指针是一个变量,其存储的值是地址,而不是值本身。(有点类似于组成原理里面的变址寻址)

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

如下面一段代码:

#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莫抹去,是该块内存显示为未用。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: