在C++中,指针是一个有趣且功能强大的特性,指针本质上也是一个对象,它存储的是对象的地址,而非值本身。
指针的定义,使用"*"进行修饰一个变量。
int *p1,*p2
如上,定义了指针p1和p2,但并未给他们赋值。
指针使用时需要结合取地址符“&”或直接指针间赋值进行使用
//定义一个变量update
int update = 20;
//使用取地址符获取update的地址存入*p_update中
int* p_update = &update;
//把p_update赋值给pr
int* pr = p_update;
cout << "update:" << update;
cout << "p_update:" << p_update;
cout << "*p_update:" << *p_update;
//使用指针进行运算
*p_update = *p_update + 1;
cout << "update:" << update;
如上输出的结果:
update:20
p_update:0x12434523452;
*p_update:20
更新之后
update:21
因为p_update指向的内存地址和update一样,而&update取出的时update内存中存储的值。
因此p_update和update完全等价。
1.)不同类型的变量,他们的值内部使用的格式不同,所以在什么指针时必须要指定指针指向的类型。
2.)创建指针时,对每个指针变量名都需要使用"*" (int p1,p2;语法创建的是一个指针p1和一个int类型的变量p2;)
3.)指针变量不仅是指针,而是指向特定类型的指针
4. )创建指针时,一定要在指针解引用运算符()之前,将指针初始化为一个确定的,适当的地址。
5. )可以使用new关键字创建指针
double * pd = new double;
*pd = 10000001.0;
使用new 创建的指针,如果内存不够时会抛出异常或返回0
在C++中对象的创建都需进行回收操作,特别是指针使用不当就会导致内存泄漏。
指针的回收是结合delete关键字+指针名
例如:
int * ps = new int;
....
delete ps;
如上代码会释放ps指向的内存,但不会删除指针ps本身。还可以将ps重新指向另外一个新分配的内存块。在使用时,一定要使用new和delete配对使用,否则将发生内存泄漏;
注:
1)不要使用delete来释放不是new分配的内存
2)不要使用delete释放同一个内存块两次
3)如果使用new[]为数组分配内存,则应使用delete[]来释放。
4)如果使用new []为一个实体分配内存,则应使用delete(没有方括号)来释放
5)对空指针应用delete是安全的
指针和常量集合时,就演变出了【指针常量】和【常量指针】这俩概念,其主要区分是看指针“*”修饰符和常量修饰符"const"谁在前面进行区分。
例如:
int simple = 20;
//常量指针
const int * a = &simple
//指针常量
int * const b = &simple
当指针与常量碰撞出火花时,哪必定和函数之间也会出现烟火吧,当指针与函数结合时,就演变出了【指针函数】和【函数指针】的概念。
返回值是一个指针类型,在调用时,需要传入内存地址。
例如:
int* addfunc(void* param) {
int b = 10;
int* p = &b;
return p;
}
int main()
{
int a = 10;
addfunc(&a);
return 0;
}
指向函数的指针变量,即本质是一个指针,把函数赋给一个函数指针。
例如:
void (*funcp)();
void point_func() {
}
int main()
{
funcp = point_func;
//只有调用了funcp之后才会指向point_func()
funcp();
return 0;
}
把一个指针本身声明为常量,可以防止修改指针指向的位置,把指针指向常量对象,可防止使用该指针来修改所指向的值。
注:C++ 种禁止将const的地址赋给非const类型的指针
在指针消亡时,想要自动回收指向的对象。可以防止内存泄露。
需要使用,auto_ptr或shared_ptr 或unique_ptr进行修饰
1)auto_ptr:在赋值时,将有百年指针的控制权转移给左边指针,右值失去了控制权,右值析构时可能会出错。
2)shared_ptr:允许多个指针指向同一个对象,析构时,最后一个析构的指针调用对象的析构函数。
3)unique_ptr:明确指出不允许共享,当发生指针赋值时,编译出错。
从分类上指针可以分为:
使用两个“**”是指向指针的指针(它指向的是*ppi的地址)
例如:
int var;
int *ptr;
int **pptr;
var = 3000;
// 获取 var 的地址
ptr = &var;
// 使用运算符 & 获取 ptr 的地址
pptr = &ptr;
// 使用 pptr 获取值
cout << "var 值为 :" << var << endl;
cout << "*ptr 值为:" << *ptr << endl;
cout << "**pptr 值为:" << **pptr << endl;
1)不要使用没有初始化的指针。
例如:
int *p;
*p = 200
2)不要直接给指针赋一个整数
例如:
double *P;
p = 1024;
3)不同类型的指针之间不能赋值
例如:
int a,*b =&a;
double *cc;
cc = b;
这种编译器就会报错。
引用可以理解为给变量起的一个别名,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
例如:
int val = 1024;
int &refVal = val
总结:
指针相当于变量,在创建时可以不用赋值,而引用相当于变量,在创建时必须赋值,且不能修改。指针指向的对象可以为空,而引用指向的对象不能为空。
引用比指针可能更加高效,因为不用考虑其有效性。使用指针时需要判断指针的有效性。
在c++中函数不能直接返回数组,可以返回一个指针指向数组,因为数组名就是一个指针。