【C++学习教程06】指针

参考资料

  • 范磊C++(第8课)
  • VS2015

指针

指针的基本概念

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200612151719709.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

空指针

在这里插入图片描述

指针与类型

在这里插入图片描述

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
	double a = 3.14;
	cout << "double is " << sizeof(a) << "byte" << endl;
	int b = 6;
	cout << "int is " << sizeof(b) << "byte" << endl;
	int *p1 = &b;
	double *p2 = &a;
	cout << "double adress is:" << p2 << endl;
	cout << "int adress is:" << p1 << endl;
	p1++;
	p2++;
	cout << "after move" << endl;
	cout << "double adress is:" << p2 << endl;
	cout << "int adress is:" << p1 << endl;
	system("pause");
	return 0;
}

结果:
在这里插入图片描述

用指针来访问

在这里插入图片描述在这里插入图片描述

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
	double a = 3.14;
	cout << "double is " << sizeof(a) << "byte" << endl;
	int b = 6;
	cout << "int is " << sizeof(b) << "byte" << endl;
	int *p1 = &b;
	double *p2 = &a;
	cout << "double adress is:" << p2 << endl;
	cout << "int adress is:" << p1 << endl;
	cout << "double num is:" << *p2 << endl;
	cout << "int num is:" << *p1 << endl;
	p1++;
	p2++;
	cout << "after move" << endl;
	cout << "double adress is:" << p2 << endl;
	cout << "num is:" << *p2 << endl;
	cout << "int adress is:" << p1 << endl;
	cout << "num is:" << *p1 << endl;
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

容易混淆的概念

在这里插入图片描述

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int i=1;
    int *p=NULL;
    cout<<"i的值:"<<i<<endl;
    cout<<"i的地址:"<<&i<<endl;
    cout<<"p的值:(P所保存的地址)"<<p<<endl;
    //cout<<"p所指向地址的值"<<*p<<endl;//访问零脂针会发生报错“程序崩溃“
    cout<<"p的地址:"<<&p<<endl;
    p=&i;
    cout<<"赋值后"<<endl;
    cout<<"p的值:(P所保存的地址)"<<p<<endl;
    cout<<"p所指向地址的值"<<*p<<endl;
    cout<<"p的地址:"<<&p<<endl;
    return 0;
}

运行后结果:
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614181415429.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

指针对数值的操作

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    typedef unsigned short int ut;
    cout<<sizeof(ut)<<endl;//2个字节
    ut i=5;
    ut *p=NULL;
    p=&i;
    cout<<"i="<<i<<endl;
    cout<<"*p="<<*p<<endl;
    cout<<"用脂针来修改存放在i中的数据"<<endl;
    *p=90;
    cout<<"i="<<i<<endl;
    cout<<"*p="<<*p<<endl;
    cout<<"用i来修改存放在i中的数据"<<endl;
    i=9;
    cout<<"i="<<i<<endl;
    cout<<"*p="<<*p<<endl;
    return 0;
}

输出结果:
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614182102476.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

为什么使用指针

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614182614319.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

栈和堆

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614183721881.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

  • 栈的数据寿命短但全局区是在程序结束后才能完全释放;
  • 堆可以由程序员决定,自由度高,优于栈和全局区;
  • 堆是通过匿名的方式来保存数据的,只能通过指针才能访问到这些匿名的数据。他的安全性是最好的。

以下为详细解释:
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614183924275.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

在这里插入图片描述

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614184204772.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

⬆️合理利用内存空间

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614184434134.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

⬆️ 空间使用灵活

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614184553535.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614184740655.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

用图来解释栈的工作原理:

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614184906229.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614184959701.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614185022480.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614185116264.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

对于堆来说:

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614185137901.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

总结:
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614185314359.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

指针与堆

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614185742721.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614185911560.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614190512462.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int *p1;
    p1=new int;//new建立堆变量
    cout<<p1<<endl;
    double *p2=new double;
    cout<<p2<<endl;
    return 0;
}

输出:
在这里插入图片描述

用指针删除堆中的空间

内存泄露
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614190816353.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int *p=new int;//new建立堆变量
    *p=36000;
    cout<<*p<<endl;
    delete p;//释放内存而不删除指针
    cout<<*p<<endl;
    p=NULL;
    p=new int;
    *p=8;
    cout<<*p<<endl;
    delete p;
    cout<<*p<<endl;
    //delete p;//反复delete会导致程序崩溃
    return 0;
}

运行结果:

![在这里插入图片描述]( https://img-blog.csdnimg.cn/2020061419245448.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

在这里内存并没有被释放掉,值得深思。

  • VS2015
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
	int *p = new int;
	*p = 23;
	delete p;
	cout << *p << endl;
	system("pause");
	return 0;
}

输出结果:
在这里插入图片描述
参考链接: 某论坛.

内存泄漏

![在这里插入图片描述]( https://img-blog.csdnimg.cn/2020061419311282.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

在堆中创建对象与删除对象&访问堆中的成员数据

#include <iostream>
using namespace std;
class Human
{
public:
    Human(){cout<<"构造函数执行"<<endl; i=9999;}
    ~Human(){cout<<"析构函数执行"<<endl;}
    int get()const{return i;}
private:
    int i;
};
int main(int argc, const char * argv[]) {
    Human Jack; //调用存放在栈中对象的方法
    cout<<Jack.get()<<endl;
    cout<<"************"<<endl;
    //以下存放在为堆中的对象
    Human *p=new Human;//此时已经创建了一个human类的对象!!他是一个匿名的!!!只能用指针找到他。
    cout<<p->get()<<endl;
    delete p;//删除这个对象也可以用p
    return 0;
}//栈中的对象会在遇到}自动析构掉

this指针

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614195715818.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

//
#include <iostream>
using namespace std;
class A
{
public:
    int get()const{return i;}
    void set(int x){i=x; cout<<"this变量保存的内存:\t"<<this<<endl;}
private:
    int i;
};
int main(int argc, const char * argv[]) {
    A a;
    a.set(9);
    cout<<"对象a的内存地址:\t"<<&a<<endl;
    cout<<a.get()<<endl;
    
    A b;
    b.set(9);
    cout<<"对象b的内存地址:\t"<<&b<<endl;
    cout<<b.get()<<endl;
    
    return 0;
}

输出结果:![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614200453441.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614200459676.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

指针的常见错误

![在这里插入图片描述]( https://img-blog.csdnimg.cn/2020061420054463.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    int *p=new int;
    *p=3;
    cout<<"将3付给p的地址后,读取指针p的值:\t"<<*p<<endl;
    delete p;
    //p=NULL;//用程序崩溃的代价来保证不会引起使用野指针
    cout<<"删除空间后,读取指针p的值:\t"<<*p<<endl;
    long *p1=new long;//p1指向了p所释放的空间
    cout<<"创建新空间后,指针p保存的地址:\t"<<p<<endl;
    *p1=9999;
    cout<<"指向新空间的指针P1保存的地址:\t"<<p<<endl;
    *p=23;//其实是将23赋给P1指向的内存空间
    cout<<"将23付给p的地址后,读取指针p的值:\t"<<*p<<endl;
    cout<<"将23付给p的地址后,读取指针p1的值:\t"<<*p1<<endl;
    return 0;
}

输出结果:

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614202058532.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

常量指针和指向常量的指针

常量指针

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614202842858.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614203029467.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw
,size_16,color_FFFFFF,t_70)

指向常量的指针

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614204320566.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614203915258.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw
,size_16,color_FFFFFF,t_70)

指向常量的常指针

及上面两个的结合,指针和指向的目标都不能改变。

总结

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200614204613934.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIyOTkyNw==,size_16,color_FFFFFF,t_70)

posted @ 2021-01-02 15:40  vrijheid  阅读(98)  评论(0)    收藏  举报