C++指针和引用

一,指针

在C++中,指针是一个有趣且功能强大的特性,指针本质上也是一个对象,它存储的是对象的地址,而非值本身。

1,指针的定义

指针的定义,使用"*"进行修饰一个变量。

int *p1,*p2

如上,定义了指针p1和p2,但并未给他们赋值。

2,指针的使用

指针使用时需要结合取地址符“&”或直接指针间赋值进行使用

	//定义一个变量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完全等价。

3,创建时的注意事项

1.)不同类型的变量,他们的值内部使用的格式不同,所以在什么指针时必须要指定指针指向的类型。
2.)创建指针时,对每个指针变量名都需要使用"*" (int p1,p2;语法创建的是一个指针p1和一个int类型的变量p2;)
3.)指针变量不仅是指针,而是指向特定类型的指针
4. )创建指针时,一定要在指针解引用运算符(
)之前,将指针初始化为一个确定的,适当的地址。
5. )可以使用new关键字创建指针

double * pd = new double;
*pd = 10000001.0;

使用new 创建的指针,如果内存不够时会抛出异常或返回0

5,指针的回收

在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是安全的

6,指针与常量

指针和常量集合时,就演变出了【指针常量】和【常量指针】这俩概念,其主要区分是看指针“*”修饰符和常量修饰符"const"谁在前面进行区分。
例如:

int simple = 20;
//常量指针
const int * a = &simple
//指针常量
int * const b = &simple
  • 常量指针:能修改指向的对象地址,但修改对象的值。
  • 指针常量:能修改对象的值,但无法修改对象地址。
    例如:
    C++指针和引用_第1张图片
    如果修改常量指针的值或修改指针常量指向的地址时,编译器都会报错。
7,指针与函数

当指针与常量碰撞出火花时,哪必定和函数之间也会出现烟火吧,当指针与函数结合时,就演变出了【指针函数】和【函数指针】的概念。

7.1指针函数

返回值是一个指针类型,在调用时,需要传入内存地址。
例如:

int* addfunc(void* param) {
	int b = 10;
	int* p = &b;
	return p;
}
int main()
{
	int a = 10;
	addfunc(&a);
	return 0;
}
7.2函数指针

指向函数的指针变量,即本质是一个指针,把函数赋给一个函数指针。
例如:

void (*funcp)();
void point_func() {

}

int main()
{    

	funcp = point_func;
         //只有调用了funcp之后才会指向point_func()
	funcp();
	return 0;
}

把一个指针本身声明为常量,可以防止修改指针指向的位置,把指针指向常量对象,可防止使用该指针来修改所指向的值。
注:C++ 种禁止将const的地址赋给非const类型的指针

8.智能指针

在指针消亡时,想要自动回收指向的对象。可以防止内存泄露。
需要使用,auto_ptr或shared_ptr 或unique_ptr进行修饰
1)auto_ptr:在赋值时,将有百年指针的控制权转移给左边指针,右值失去了控制权,右值析构时可能会出错。
2)shared_ptr:允许多个指针指向同一个对象,析构时,最后一个析构的指针调用对象的析构函数。
3)unique_ptr:明确指出不允许共享,当发生指针赋值时,编译出错。

9,指针的分类

从分类上指针可以分为:

  • 指向一个对象
  • 指向紧邻对象所占空间的下一个位置
  • 空指针,意味指针没有指向任何对象
  • 无效指针
    其中void指针 是一种特殊的指针类型,可用于存放任意对象的地址。
    他的主要作用
    1)和别的指针比较
    2)作为函数的输入或者输出
    3)赋值给另外一个void
    指针
    它不能操作指针所指的对象,因为不知道对象是什么类型。

使用两个“**”是指向指针的指针(它指向的是*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;
10,注意事项

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++中函数不能直接返回数组,可以返回一个指针指向数组,因为数组名就是一个指针。

你可能感兴趣的:(C++,c++,智能指针,函数指针,指针常量,指针与引用)