为啥unique_ptr的移动比shared_ptr赋值要慢?
在Modern Effective C++中,提倡使用unique_ptr代替裸指针,因为unique_ptr的大小和性能与裸指针基本一致但更安全,而shared_ptr由于由原子变量的存在性能更差,但是同步赋值试下来,unique_ptr的移动很慢。
#include <memory>#include <chrono>#include <utility>#include <iostream>int main(){ #define COUNT 100000000 using MyType = int; decltype(auto) u = std::make_unique<MyType>(); decltype(auto) s = std::make_shared<MyType>(); decltype(auto) r = new MyType; decltype(auto) u1 = std::move(u); decltype(auto) s1 = s; decltype(auto) r1 = r; auto start = std::chrono::high_resolution_clock::now(); auto finish = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> elapsed = finish - start; start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < COUNT; ++i) r = r1; finish = std::chrono::high_resolution_clock::now(); elapsed = finish - start; std::cout << "ptr: " << elapsed.count() << "s\n"; start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < COUNT; ++i) u = std::move(u1); finish = std::chrono::high_resolution_clock::now(); elapsed = finish - start; std::cout << "unique_ptr: " << elapsed.count() << "s\n"; start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < COUNT; ++i) s = s1; finish = std::chrono::high_resolution_clock::now(); elapsed = finish - start; std::cout << "shared_ptr: " << elapsed.count() << "s\n"; }
运行结果:
-O0 肯定是不行的,C++ 比速度一定要开优化。
不开优化的话,这里的 std::move 怎么说也是一个函数调用。多了一个函数调用就没法比了。
.L51: mov rax, QWORD PTR [rbp-48] mov rdi, rax call std::remove_reference<std::unique_ptr<int, std::default_delete<int> >&>::type&& std::move<std::unique_ptr<int, std::default_delete<int> >&>(std::unique_ptr<int, std::default_delete<int> >&) mov rdx, rax lea rax, [rbp-120] mov rsi, rdx mov rdi, rax call std::unique_ptr<int, std::default_delete<int> >::operator=(std::unique_ptr<int, std::default_delete<int> >&&) add DWORD PTR [rbp-24], 1.L50: cmp DWORD PTR [rbp-24], 999999 jle .L51
另外,你这个 unique_ptr 的测试里还多了一个 delete ,因为在第二轮循环 u1 为 nullptr ,u 就被 delete 掉了。
在C++中,unique_ptr
和shared_ptr
是两种常用的智能指针类型,它们在内存管理方面的工作方式有所不同,这导致了它们在性能上的差异。
unique_ptr
代表独占所有权的智能指针。当一个unique_ptr
对象被移动时,所有权会发生转移,原始unique_ptr
将变为空。这个所有权转移是通过std::move
来完成的,它实际上是一个非常轻量级的操作,只涉及到设置一个内部指针。因此,unique_ptr
的移动速度是非常快的。
相比之下,shared_ptr
则代表共享所有权的智能指针。当一个shared_ptr
对象被赋值时,它会增加引用计数。如果这个引用计数增加了,那么就会为共享的原始对象分配更多的内存来存储这个计数。由于涉及到内存分配和原子操作,因此shared_ptr
的赋值操作比unique_ptr
的移动操作要慢得多。
在你的代码中,你测试了三种类型的指针:裸指针、unique_ptr
和shared_ptr
。对于裸指针,你只是进行了赋值操作,而没有涉及到内存分配或释放。因此,这个操作是最快的。对于unique_ptr
,你使用了移动语义来进行赋值,这是一个非常快速的操作。而对于shared_ptr
,你进行了赋值操作,这涉及到了引用计数的增加,因此速度较慢。
总的来说,由于unique_ptr
和shared_ptr
在实现上存在本质的不同,导致了它们在性能上的差异。在实际编程中,我们应根据具体需求选择使用哪种类型的智能指针。如果只需要独占所有权,那么使用unique_ptr
是更好的选择;如果需要共享所有权,那么可以使用shared_ptr
。
我正在使用STD::UNIQUE_PTR在类上创建一些公共成员,这些成员必须是不可复制或可移动的。但是STD::UNIQUE_PTR是可移动的,我想知道如果有人移动STD::UNIQUE_PTR包含的指针,然后我尝试访问被移动的那个类的STD::UNIQUE_PTR成员,会发生什么。 我所需要的就是使std::unique_ptr不可移动,并简单地保存一个唯一的指针,该指针不能从拥有它的类中移动或
我有一个类实例的向量。这些实例中的每一个都有一个指向另一个类的unique_ptr。由于我从来不尝试复制类实例,甚至不尝试共享指针,所以我觉得unique_ptr比shared_ptrs更合适,因为指针不是共享的,而是只能通过类实例访问。 这是不好的练习吗?为什么这行不通?我知道将一个实例复制到一个唯一的指针将是错误的,但是既然我移动了它,我不明白为什么不允许这样做? 我必须创建一个自定义移动构造
代码如下: 我假设错误发生在insert函数中,并且与参数初始化有关。 bintree.cpp:65:27:错误:使用删除的函数'std::unique_ptr<_tp,_dp>::unique_ptr(const std::unique_ptr<_tp,_dp>&)[with_tp=bintreenode;_dp=std::default_delete>]“tree.insert(tree.ro
本文向大家介绍Vue.js 动态为img的src赋值方法,包括了Vue.js 动态为img的src赋值方法的使用技巧和注意事项,需要的朋友参考一下 需求是这样: ajax获取数据如下 然后渲染列表到页面,如果男,则将img的src设为"images/male.png",反之设为"images/female.png" 两个都可以实现,为了在html中看起来舒服点还是用filter吧,虽然也就一个判断
本文向大家介绍在C / C ++中为浮点数和比较赋一个整数,包括了在C / C ++中为浮点数和比较赋一个整数的使用技巧和注意事项,需要的朋友参考一下 整数是一种数据类型,用于定义一个包含所有正,负或零个非小数值的数字。这些不能有小数。 浮点数是一种数据类型,用于定义具有小数值的数字。这些也可以有小数。 现在,当我们为两者输入相同的值时,我们将检查编译器返回的float和integer值是什么。