-
右值引用与move
-
右值引用
zhuanlan.zhihu.com/p/335994370
左值右值:左值可以取地址、位于等号左边;而右值没法取地址,位于等号右边。
再看下右值引用,右值引用的标志是&&,顾名思义,右值引用专门为右值而生,可以指向右值,不能指向左值。被声明出来的左、右值引用都是左值。 因为被声明出的左右值引用是有地址的,也位于等号左边。
1.从性能上讲,左右值引用没有区别,传参使用左右值引用都可以避免拷贝。
2.右值引用可以直接指向右值,也可以通过std::move指向左值;而左值引用只能指向左值(const左值引用也能指向右值)。
3.作为函数形参时,右值引用更灵活。虽然const左值引用也可以做到左右值都接受,但它无法修改,有一定局限性。
-
std::move应用场景
1 实现移动语义。在实际场景中,右值引用和std::move被广泛用于在STL和自定义类中实现移动语义,避免拷贝,从而提升程序性能。 在没有右值引用之前,一个简单的数组类通常实现如下,有构造函数、拷贝构造函数、赋值运算符重载、析构函数等。深拷贝/浅拷贝在此不做讲解。
2 vector::push_back使用std::move提高性能,std::move本身只做类型转换,对性能无影响。 我们可以在自己的类中实现移动语义,避免深拷贝,充分利用右值引用和std::move的语言特性。
-
-
智能指针
zhuanlan.zhihu.com/p/54078587?…
-
shared_ptr
shared_ptr p(ptr):传入ptr指针作为shared_ptr的指向
shared_ptr p(unique_ptr):传入unique_ptr作为shared_ptr的指向
shared_ptr p(ptr,de):传入ptr作为shared_ptr的指向,并用de取代delete进行释放
shared_ptr p(p2,de):传入shared_ptr的拷贝,并利用de取代delete进行释放
p.reset():将shared_ptr置空
p.reset(ptr):将shared_ptr指针指向传递入内的ptr中
p.reset(ptr,de):将shared_ptr指针指向传递入内的ptr中,并用de取代delete进行释放
-
可能出现的陷阱
(1)不使用相同的内置指针值初始化(或reset)多个智能指针。
(2)不delete get()返回的指针。
(3)不使用get()初始化或reset另一个智能指针。
(4)如果使用get()返回的指针,当最后一个对应的智能指针销毁后,指针就变为无效。
(5)如果使用智能指针管理的资源不是new分配的内存,记住传递给它一个删除器。
-
应注意的问题
(1)专门用于共享所有权,内部使用引用计数use_count() ,因此可以支持复制、参数传递等,也是用于管理单个堆内存对象的。
(2)同样没有release() 函数。
-
-
auto_ptr
auto_ptr事实上是一个类,在构造对象时获取对象的管理权, 无需考虑释放动态内存开辟的空间,在析构函数中直接释放,不会出现内存泄漏的问题。
-
可能出现的缺陷
1.一个指针变量指向的空间不能由两个auto_ptr管理,不然会析构两次,使程序崩溃。
2.auto_ptr的拷贝构造,将源指针的管理权交给目标指针,会使得源指针悬空,解引用是会出现很多问题。
3.auto_ptr不能用来管理数组,析构函数中用的是delete
-
应注意的问题
(1) 尽量不要使用“operator=”。如果使用了,请不要再使用先前对象。
(2) 记住 release() 函数不会释放对象,仅仅归还所有权。
(3) std::auto_ptr 最好不要当成参数传递(读者可以自行写代码确定为什么不能)。
(4) 由于 std::auto_ptr 的“operator=”问题,有其管理的对象不能放入 std::vector 等容器中。
-
-
scoped_ptr
-
scoped_ptr防拷贝:
1.拷贝构造函数和赋值运算符重载函数只声明不实现
2.用private对其进行访问限定,防止在类外定义
-
缺陷
不能进行拷贝构造,管理的对象不能共享所有权,功能不全面。
-
应注意的问题
(1)scoped_ptr 没有 release 函数
(2)没有重载 operator=,不会导致所有权转移,但无法赋值,拷贝智能指针。
(3)scoped_ptr 没有重载 operator*
(4)没有重载 operator=
-
-
scoped_array
scoped_array 和 scoped_ptr的功能是一样的,只是scoped_array管理的对象是数组,需要重载[]的形式。
-
应注意的问题
(1)用于管理动态数组
(2) boost::scoped_array my_memory(new Simple[2]); // 使用内存数组来初始化
-
-
unique_ptr
unique_ptr p2(p1.release());//release将p1置为空
unique_ptrp3(new string("text"));//将所有权从p3转移到p2
p2.reset(p3.release());//reset释放了p2原来指向的内存
-
weak_ptr
weak_ptr w:设置一个空的weak_ptr
weak_ptr w(ptr):将weak_ptr赋值指向与ptr指向相同的对象
w=p;w与p共享对象,其中p可以为shared_ptr或者另一个weak_ptr
w.reset():将w置空
w.use_count():与w共享对象的shared_ptr的数量
w.expired():若w.use_count==0,则返回true,反之返回false
w.lock():若expired==true,则返回一个空的shared_ptr,反之返回一个指向w的对象的shared_ptr
-
注意:
由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock,此函数检查weak_ptr指向的对象是否存在。如果存在,lock返回一个指向共享对象的shared_ptr,如果不存在,lock将返回一个空指针
-
-