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

参考资料

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

指针

指针的基本概念

在这里插入图片描述

空指针

在这里插入图片描述

指针与类型

在这里插入图片描述

#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;
}

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

指针对数值的操作

#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;
}

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

为什么使用指针

在这里插入图片描述

栈和堆

在这里插入图片描述

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

以下为详细解释:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

⬆️合理利用内存空间

在这里插入图片描述

⬆️ 空间使用灵活

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

对于堆来说:

在这里插入图片描述

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

指针与堆

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

#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;
}

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

用指针删除堆中的空间

内存泄露
在这里插入图片描述

#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;
}

运行结果:

在这里插入图片描述

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

  • 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;
}

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

内存泄漏

在这里插入图片描述

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

#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指针

在这里插入图片描述

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

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

在这里插入图片描述

指针的常见错误

在这里插入图片描述

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

输出结果:

在这里插入图片描述

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

常量指针

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

指向常量的指针

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

指向常量的常指针

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

总结

在这里插入图片描述

原文地址:https://www.cnblogs.com/vrijheid/p/14222988.html