C++指针

1、什么是指针: 

指针就是用来保存内存地址的变量。


2、指针的地址和指针保存的地址

指针的地址是指针本身在内存中的位置,该地址中可以保存另一个变量的地址,即指针保存的地址。
int main()
{
	int a = 100;
	int *p = &a;

	//&a和p拥有相同地址,p保存的变量地址即是&a
	cout<<"a的地址:"<<&a<<endl;
	cout<<"p所保存的地址:"<<p<<endl;
	
	//指针p自身的地址
	cout<<"p自身的地址:"<<&p<<endl;

	//指针p中保存的地址的值,在p前面加“*”进行解引用操作,即可获得它所指针地址的值
	cout<<"p保存的地址的值:"<<*p<<endl;

	//通过对指针p自身地址解引用,获得它所保存的地址
	cout<<"p保存的地址的值:"<<*&p<<endl;

	//同上,得到 保存的地址后,再解引用,就可以获得保存地址里面的实际数据
	cout<<"p保存的地址的值:"<<**&p<<endl;

	return 0;
}


3、指针修改它所指向的内存中的数据
指针通过解引用*运算符访问并读取内存地址中的数据,并可以对数据进行修改。

int main()
{
	int a = 100;
	int *p = &a;

	//a的值也会随之而变,因为*p和a占用引用的是同一块物理地址
	*p = 200;
	cout<<a<<endl;	//--->200
	cout<<*p<<endl;	//--->200

	//*p的值也会随之而变,理由同上
	a = 300;
	cout<<a<<endl;	//--->300
	cout<<*p<<endl;	//--->300

	return 0;
}


4、修改指针保存的地址
允许将一个变量的地址赋给一个已经保存了其它地址的指针变量
int main()
{
	int a = 100;
	int b = 200;

	//现在指针p中保存的是变量a的地址
	int *p = &a;
	cout<<"a的地址:"<<&a<<endl;		//---> a = 100
	cout<<"p所保存的地址:"<<p<<endl;//---> *p = 100

	//现在指针p中保存的是变量b的地址
	p = &b;
	cout<<"b的地址:"<<&b<<endl;		//---> b = 200
	cout<<"p所保存的地址:"<<p<<endl;//---> *p = 200

	return 0;
}


5、对象在堆与栈中的不同
(1)堆中的对象:通过new关键字动态开辟的存储空间,生命周期和整个程序运行周期相同,需要手动delete释放
class MyClass
{
public:
	MyClass(){cout<<"执行构造函数"<<endl;}
	~MyClass(){cout<<"执行析构函数"<<endl;}
};

int main()
{
	MyClass *p = new MyClass();
	delete p;//手动释放,否则p声明周期会一直持续到程序结束
	return 0;
}
(2)栈上的对象:程序执行到对象所以有效区域的右大括号时被销毁,栈的生命周期随着它所在函数的执行完毕而结束

class MyClass
{
public:
	MyClass(){cout<<"执行构造函数"<<endl;}
	~MyClass(){cout<<"执行析构函数"<<endl;}
};

int main()
{
	MyClass m;
	return 0;
}//在这里销毁了对象m

6、delete指针后,为其赋一个NULL值,以免发生难以调试的错误
int main()
{
	int *p = new int;
	*p = 100;

	//虽然delete了,但也只是说明这块空间现在谁都可以用了,不再被p独占,但是并没有对上面保存的地址进行任何修改
	delete p;

	//对p上的空间置空,否则p会变成野指针
	//p = NULL;

	//紧接着分配另一块内存空间,这块空间有可能就是编译器刚刚收回的p指针所保存的地址
	int *p1 = new int;
	*p1 = 200;

	//因为p没有被置空,所以还可以继续使用,上面还存在以前分配的空间地址
	//且p1也指向这块空间,所以对p的操作,会影响p1的结果
	*p = 300;

	//p1现在将会是p修改的值
	cout<<*p1<<endl;
	return 0;
}

7、指针的运算
(1)自加自减:将当前的内存地址前后偏移N个字节(字节大小由指针指向的数据类型的大小决定)
int main()
{
	int *p = new int;//sizeof(int) = 4bit
	++p;//向后移动4个字节
	--p;//向前移动4个字节
	p += 2;//向后移8个字节
	p -= 2;//向前移8个字节
	return 0;
}
(2)指针的赋值运算
int main()
{
	int *p = new int;
	int *p1 = new int;
	p = p1;//p现在保存的是p1所存储的内存地址,但是p本身的地址并不会改变
	return 0;
}
(3)指针相减:计算出地址差(结果×数据类型大小=字节数)
注:两个指针不能做相加操作
int main()
{
	int *p1 = new int;
	int *p2 = new int;
	cout<<p2<<endl;
	int a = p1 -p2;//计算两块内存之间的地址差
	p1 += a;//将p1的内存单元地址加上地址差a,就等于p2的内存地址了
	cout<<p1<<endl;
	return 0;
}
(4)指针的比较运算
int main()
{
	int *p1 = new int;
	int *p2 = new int;
	if (p1 > p2)
	{
		cout<<"p1 bigger"<<endl;
	}
	else
	{
		cout<<"p2 bigger"<<endl;
	}
	return 0;
}

8、带const修饰符的指针
(1)常量指针:指针是常量,不能修改;它所指向的内容是非常量,可以修改
class MyClass
{
public:
	MyClass(){cout<<this<<endl;}
	~MyClass(){}
public:
	void set(int n){m_nVal = n;}
private:
	int m_nVal;
};

int main()
{
	//常量指针:指向的地址不能修改,指向的内容可以修改
	MyClass *const p = new MyClass;

	//指针存储的地址不能修改
	//p++;

	//指针指向的内容可以修改
	p->set(1);

	return 0;
}
(2)指向常量的指针:指针指向的内容是常量,不能修改;指针所存储的内存地址可以修改
int main()
{
	//指向常量的指针:指向的地址可以修改,指向的内容不能修改
	MyClass const* p = new MyClass;
	//const MyClass * p = new MyClass;

	//指针存储的地址可以修改
	p++;

	//指向的内容不可以修改
	//p->set(1);

	return 0;
}
(3)指向常量的常指针:指针存储的地址和所指向的内容都不能修改
int main()
{
	//指向常量的指针:指向的地址可以修改,指向的内容不能修改
	//const MyClass *const p = new MyClass;
	 MyClass const*const p = new MyClass;

	//指针存储的地址可以修改
	//p++;

	//指向的内容不可以修改
	//p->set(1);

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纯洁码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值