C++语言--指针--3.1--什么是地址、用指针来保存内存地址、为什么使用指针、指针的常见错误
2017-01-14 16:29
639 查看
前言:C++系列之指针!
1.指针
指针是用来保存内存地址的变量。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201701/14/178ca91a3abe45885ff489b6a6f5be70)
2.用指针来保存地址
2.1 指针与类型变量
![](https://oscdn.geek-share.com/Uploads/Images/Content/201701/14/b06981873fbb05a9313508a93d5049ce)
从上面我们可以看到指针P1指向的a为int类型,指针P2指向的b为double类型。当我们分别把指针P1,P2分别加一时,
根据输出的结果可以看出,P1前后的变化是移动了4个字节,P2前后的变化是移动了8个字节(拿出计算机计算就知道了)。
当我们在后端加入P2=P1,编译报错,这是为什么了?因为他俩指针指向的类型不同,这也是它编译不过的原因。
指针的类型必须与它所指向的变量的类型相匹配。假如不相匹配,那么就会报错。
2.2 指针的地址与指针中保存的某个变量的地址
![](https://oscdn.geek-share.com/Uploads/Images/Content/201701/14/7a3715ff08c0b040dd165d7a34423476)
我们可以看到,经过P=&i的变换,无论是i或者是P他们自身的地址都保持不变(这里的P的地址是P的内存地址),但是P的值发生了改变。
2.3 更换指针保存的地址
![](https://oscdn.geek-share.com/Uploads/Images/Content/201701/14/6fd129fb37adc07ddad34146cf383a33)
这样我们就通过了改变指针保存的地址从而改变获取到的值。
3.为什么使用指针
![](https://oscdn.geek-share.com/Uploads/Images/Content/201701/14/9dbc70c90a16e189216d5b9f3c017732)
先介绍两种最主要的两种
1、栈区:由编译器自动分配且释放,该区一般存放函数的参数值和局部变量
2、堆区:一般由程序员分配和释放,程序员不释放,程序结束后由操作系统自动回收、释放。
三、对于栈区的局部变量和参数当程序一旦运行完后,就会被系统自动释放并且清除。所以当程序运行,函数调用完毕时需要反回该函数中的局部变量和方法的参数值时无法做到。虽然全局变量可以解决这个问题,全局变量可以被整个类的成员函数共享,所以很容易被改变之。
而堆可以很好的解决这一问题。
四、堆内存的使用示例,使用new关键字创建堆内存,堆内存是匿名的,所以要用指针保存这个堆内存单元的地址,方便该堆内存空间下数据访问。
#include <iostream>
using namespace std;
int main()
{
//让p指针指向一个double类型的堆内存空间分配8个字节
double *p = new double;
//向p指针所指向的堆内存空间中写入数据
*p = 1.44;
cout<<*p<<endl;
//让p指针释放指向的堆内存
p = NULL;
//输出p指针现在的指向
cout<<p<<endl;
return 0;
}
4.指针的常见错误
先看一段代码:
[cpp] view
plain copy
<span style="font-size:18px;">// HelloWorld.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int *p=new int;
*p=3;
cout<<"将3赋值给指针p后,指针p的值为:"<<*p<<endl;
delete p;
cout<<"将内存删除后,指针p的值为:"<<*p<<endl;
long *p1=new long;
cout<<"重新申请空间p1后,指针p指向的地址为:"<<p<<endl;
*p1=999;
cout<<"指向新空间的指针p1的地址为:"<<p1<<endl;
*p=50;
cout<<"将50赋值给指针p后,指针p的值为:"<<*p<<endl;
cout<<"将50赋值给指针p后,指针p1的值为:"<<*p1<<endl;
system("pause");
return 0;
}
</span>
这段代码的指向结果如下:
将3赋值给指针p后,指针p的值为:3
将内存删除后,指针p的值为:-17891602
重新申请空间p1后,指针p指向的地址为:002E2C40
指向新空间的指针p1的地址为:002E2C40
将50赋值给指针p后,指针p的值为:50
将50赋值给指针p后,指针p1的值为:50
请按任意键继续. . .
可以看出,在删除指针p所指向的内存后,并没有为p重新赋值,从而使p依然指向原来的内存地址。然后重新申请内存地址的时候系统将上一次释放的内存(即p指向的内存)地址给了p1,使指针p和p1同时指向同一块内存,然后后果可想而知。
所以,在释放内存后最好为原来指向他的指针赋值为空指针。即添加一句:p=0;虽然在后面调用的时候会导致程序崩溃,但是这样就会提醒我们,在前面出现了上面的问题。
1.指针
指针是用来保存内存地址的变量。
2.用指针来保存地址
2.1 指针与类型变量
从上面我们可以看到指针P1指向的a为int类型,指针P2指向的b为double类型。当我们分别把指针P1,P2分别加一时,
根据输出的结果可以看出,P1前后的变化是移动了4个字节,P2前后的变化是移动了8个字节(拿出计算机计算就知道了)。
当我们在后端加入P2=P1,编译报错,这是为什么了?因为他俩指针指向的类型不同,这也是它编译不过的原因。
指针的类型必须与它所指向的变量的类型相匹配。假如不相匹配,那么就会报错。
2.2 指针的地址与指针中保存的某个变量的地址
我们可以看到,经过P=&i的变换,无论是i或者是P他们自身的地址都保持不变(这里的P的地址是P的内存地址),但是P的值发生了改变。
2.3 更换指针保存的地址
这样我们就通过了改变指针保存的地址从而改变获取到的值。
3.为什么使用指针
先介绍两种最主要的两种
1、栈区:由编译器自动分配且释放,该区一般存放函数的参数值和局部变量
2、堆区:一般由程序员分配和释放,程序员不释放,程序结束后由操作系统自动回收、释放。
三、对于栈区的局部变量和参数当程序一旦运行完后,就会被系统自动释放并且清除。所以当程序运行,函数调用完毕时需要反回该函数中的局部变量和方法的参数值时无法做到。虽然全局变量可以解决这个问题,全局变量可以被整个类的成员函数共享,所以很容易被改变之。
而堆可以很好的解决这一问题。
四、堆内存的使用示例,使用new关键字创建堆内存,堆内存是匿名的,所以要用指针保存这个堆内存单元的地址,方便该堆内存空间下数据访问。
#include <iostream>
using namespace std;
int main()
{
//让p指针指向一个double类型的堆内存空间分配8个字节
double *p = new double;
//向p指针所指向的堆内存空间中写入数据
*p = 1.44;
cout<<*p<<endl;
//让p指针释放指向的堆内存
p = NULL;
//输出p指针现在的指向
cout<<p<<endl;
return 0;
}
4.指针的常见错误
先看一段代码:
[cpp] view
plain copy
<span style="font-size:18px;">// HelloWorld.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int *p=new int;
*p=3;
cout<<"将3赋值给指针p后,指针p的值为:"<<*p<<endl;
delete p;
cout<<"将内存删除后,指针p的值为:"<<*p<<endl;
long *p1=new long;
cout<<"重新申请空间p1后,指针p指向的地址为:"<<p<<endl;
*p1=999;
cout<<"指向新空间的指针p1的地址为:"<<p1<<endl;
*p=50;
cout<<"将50赋值给指针p后,指针p的值为:"<<*p<<endl;
cout<<"将50赋值给指针p后,指针p1的值为:"<<*p1<<endl;
system("pause");
return 0;
}
</span>
这段代码的指向结果如下:
将3赋值给指针p后,指针p的值为:3
将内存删除后,指针p的值为:-17891602
重新申请空间p1后,指针p指向的地址为:002E2C40
指向新空间的指针p1的地址为:002E2C40
将50赋值给指针p后,指针p的值为:50
将50赋值给指针p后,指针p1的值为:50
请按任意键继续. . .
可以看出,在删除指针p所指向的内存后,并没有为p重新赋值,从而使p依然指向原来的内存地址。然后重新申请内存地址的时候系统将上一次释放的内存(即p指向的内存)地址给了p1,使指针p和p1同时指向同一块内存,然后后果可想而知。
所以,在释放内存后最好为原来指向他的指针赋值为空指针。即添加一句:p=0;虽然在后面调用的时候会导致程序崩溃,但是这样就会提醒我们,在前面出现了上面的问题。
相关文章推荐
- 指针自身的地址、指针保存的地址和指针保存地址处的内容,为什么使用指针
- 指针和引用有什么分别;如果传引用比传指针安全,为什么?如果我使用常量指针难道不行吗?
- C++语言笔试题目 C++中为什么用模板类&& 类中如何使用const &&函数重载,我们靠什么来区分调用的那个函数?靠返回值判断可以不可以
- 指针和引用有什么分别;如果传引用比传指针安全,为什么?如果我使用常量指针难道不行吗?
- 为什么 Python被Google选为TensorFlow的开发语言呢?使用 Python比C++语言进行机器学习有什么优势?
- C语言指针使用中的常见错误
- jsp request,正确使用. 为什么不能使用 getAttribute 得到保存的数据
- iis“地址已被使用” 错误
- 指针与字符串操作的一些常见错误
- 关于CSDN_blog的使用错误记录(不知道为什么CSDN不去改这些错误,难道你们用起来舒服???)
- [错误记录]关于指针传递获得数据使用错误问题....
- vc中的使用技巧和常见错误
- 大内高手—常见内存错误(部分内定为指针相关)
- 安装了dns且可以正常工作为什么还有"没有可以使用的"DNS服务器"的错误
- java下Class.forName的作用是什么,为什么要使用它?
- 使用***版软件中常见的一些错误代码
- Export/Import 使用技巧与常见错误
- 使用APPlication,Session,Cookie和ViewState等对象保存信息的区别是什么?
- “原型”是什么?为什么要使用“原型”
- 如何获取变量类型及void指针中保存的指针指向什么类型的变量