【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变量保存的内存:\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;
}
输出结果:
指针的常见错误
#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;
}
输出结果:
常量指针和指向常量的指针
常量指针
指向常量的指针
指向常量的常指针
及上面两个的结合,指针和指向的目标都不能改变。