引用与指针的区别和联系
- 指针是实体,会为其分配内存,且可以允许多级指针
- 引用创建时必须初始化且不可变(只能初始化一次故不用const),指针创建时无须初始化但最好初始化以防止NULL
- 二者自增(++)结果不同,引用是值进行自增,而指针是地址进行自增;
- sizeof 结果不同,sizeof 引用得到的是所指向的变量(对象)的大小,而sizeof 指针得到的是指针本身的大小
- 引用访问是直接访问原对象,指针则是间接访问
- 作为参数给函数传参不同,引用传参会比指针传参更安全,原因见下一问
- 联系
- 引用的内部使用指针实现的
- 引用是受了限制的指针
为什么传引用比传指针安全?
- 引用在创建的同时必须初始化,保证引用的对象是有效的,所以不存在NULL引用;而指针在定义的时候不必初始化,所以,指针则可以是NULL,可以在定义后面的任何地方重新赋值
- 引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用;而指针在任何时候都可以改变为指向另一个对象
- 引用的创建和销毁并不会调用类的拷贝构造函数
因为不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,所以比指针安全。
由于 const 指针仍然存在空指针,并且有可能产生野指针,所以还是不安全。解决方案是智能指针。
介绍一下智能指针
智能指针,将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。
智能指针就是一种栈上创建的对象,函数退出时会调用其析构函数,这个析构函数里面往往就是一堆计数之类的条件判断,如果达到某个条件,就把真正指针指向的空间给释放了。
使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,野指针,程序发生异常时内存泄露等问题等,使用智能指针能更好的管理堆内存。
常用的智能指针
智能指针在C++11版本之后提供,包含在头文件
在C++98中,有std::auto_ptr
,但它有很多问题。 不支持复制(拷贝构造函数)和赋值(operator =),但复制或赋值的时候不会提示出错。所以可能会造成程序崩溃。
auto_ptr<string> p1(new string ("auto") ; //#1 auto_ptr<string> p2; //#2 p2 = p1; //#3
在语句#3中,p2接管string对象的所有权后,p1的所有权将被剥夺,可防止p1和p2的析构函数试图刪同—个对象;
如果再访问p1指向的内容则会导致程序崩溃,因为p1不再指向有效的数据。std::auto_ptr
被unique_ptr代替。
- unique_ptr
某个时刻只能有一个unique_ptr指向一个给定的对象。
不支持复制和赋值,但比auto_ptr好,直接赋值会编译出错。实在想赋值的话,需要使用std::move
。 - shared_ptr
基于引用计数的智能指针,提供所有权共享的智能指针,在最后一个指向共享对象的shared_ptr被销毁时释放共享对象。 - weak_ptr
弱智能指针对象,它不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的智能指针。将一个weak_ptr绑定到一个shared_ptr对象,不会改变shared_ptr的引用计数。一旦最后一个所指向对象的shared_ptr被销毁,所指向的对象就会被释放,即使此时有weak_ptr指向该对象,所指向的对象依然被释放。