Ven*_*emo 88 c++ performance smart-pointers c++11
与C++ 11中的普通指针相比,智能指针的开销是多少?换句话说,如果我使用智能指针,我的代码会变慢吗?如果是这样,速度会慢多少?
具体来说,我问的是C++ 11 std::shared_ptr和std::unique_ptr.
显然,推下堆栈的东西会变得更大(至少我认为是这样),因为智能指针也需要存储其内部状态(引用计数等),问题是,这是多少影响我的表现,如果有的话?
例如,我从函数而不是普通指针返回一个智能指针:
std::shared_ptr<const Value> getValue();
// versus
const Value *getValue();
或者,例如,当我的一个函数接受智能指针作为参数而不是普通指针时:
void setValue(std::shared_ptr<const Value> val);
// versus
void setValue(const Value *val);
lis*_*rus 162
std::unique_ptr 只有当你为它提供一些非平凡的删除器时才会有内存开销.
std::shared_ptr 总是有参考计数器的内存开销,虽然它非常小.
std::unique_ptr 只有在构造函数期间(如果它必须复制提供的删除器和/或null初始化指针)和析构函数(以销毁拥有的对象)时才有时间开销.
std::shared_ptr在构造函数(创建引用计数器),析构函数(减少引用计数器并可能销毁对象)和赋值运算符(增加引用计数器)中有时间开销.由于线程安全保证std::shared_ptr,这些增量/减量是原子的,因此增加了一些额外的开销.
请注意,在解除引用(获取对拥有对象的引用)时,它们都没有时间开销,而此操作似乎是指针最常见的操作.
总而言之,有一些开销,但它不应该使代码变慢,除非你不断创建和销毁智能指针.
Che*_*Alf 24
与所有代码性能一样,获得硬信息的唯一真正可靠的方法是测量和/或检查机器代码.
这就是说,简单的推理说
你可以期待调试版本中的一些开销,因为例如operator->必须作为函数调用执行,以便你可以进入它(这反过来又是由于一般不支持将类和函数标记为非调试).
因为shared_ptr你可以期望在初始创建时有一些开销,因为这涉及动态分配控制块,并且动态分配比C++中的任何其他基本操作要慢得多(尽可能使用make_shared,以最小化开销).
另外,对于shared_ptr维护引用计数有一些最小的开销,例如,当传递一个shared_ptrby值时,但是没有这样的开销unique_ptr.
记住第一点,在测量时,为调试和发布版本执行此操作.
国际C++标准化委员会已经发布了一份关于性能的技术报告,但这是在2006年之前,unique_ptr并且shared_ptr被添加到标准库中.不过,智能指针在那时仍然是旧帽子,所以报告也考虑了这一点.引用相关部分:
"如果通过普通的智能指针访问值比通过普通指针访问它要慢得多,那么编译器就无法有效地处理抽象.在过去,大多数编译器都有很大的抽象惩罚,而且目前的编译器仍有一些.但是,据报道至少有两个编译器的抽象罚分低于1%而另一个编译器罚款3%,因此消除这种开销完全属于现有技术水平.
作为一个明智的猜测,截至2014年初,当今最流行的编译器已经实现了"最先进的技术".
Lot*_*har 20
我的答案与其他答案不同,我真的很想知道他们是否曾编写过代码.
shared_ptr具有很大的创建开销,因为它是控制块的内存分配(它将ref计数器和指针列表保存到所有弱引用).它也有巨大的内存开销,因为std :: shared_ptr总是一个2指针元组(一个到对象,一个到控制块).
如果将shared_pointer作为值参数传递给函数,那么它将比正常调用慢至少10倍,并在代码段中创建大量代码以进行堆栈展开.如果你通过引用传递它,你会得到一个额外的间接,这在性能方面也会更差.
这就是为什么你不应该这样做,除非该功能真正涉及所有权管理.否则使用"shared_ptr.get()".它的目的不是确保在正常的函数调用期间不会杀死您的对象.
如果你发疯并在编译器中的抽象语法树之类的小对象上使用shared_ptr,或者在任何其他图形结构中的小节点上使用shared_ptr,你会看到巨大的性能下降和巨大的内存增加.我见过一个解析器系统,在C++ 14上市之后不久,程序员学会正确使用智能指针之前,它就被重写了.重写比旧代码慢了很多.
根据定义,它不是一个银弹,原始指针也不错.糟糕的程序员是糟糕的,坏的设计是坏的.谨慎设计,设计时考虑到明确的所有权,并尝试主要在子系统API边界上使用shared_ptr.
如果您想了解更多信息,可以观看Nicolai M. Josuttis关于"C++中共享指针的实际价格"的好话题https://vimeo.com/131189627
 
它深入探讨了写入障碍的实现细节和CPU架构,原子锁等等一旦听完,你永远不会谈论这个功能便宜.如果你只想要一个较慢的数据证明,跳过前48分钟并观察他运行的示例代码在任何地方使用共享指针时运行速度慢180倍(用-O3编译).
Cla*_*dgz 12
换句话说,如果我使用智能指针,我的代码会变慢吗?如果是这样,速度会慢多少?
慢点?最有可能的是,除非你使用shared_ptrs创建一个巨大的索引,而你没有足够的内存使你的计算机开始起皱,就像一位老太太被来自远方的难以忍受的力量猛烈地撞倒在地.
使代码变慢的原因是搜索速度缓慢,不必要的循环处理,大量数据副本以及对磁盘的大量写入操作(如数百个).
智能指针的优点都与管理有关.但是必要的开销是多少?这取决于您的实施.假设您正在迭代3个阶段的数组,每个阶段都有1024个元素的数组.smart_ptr为这个过程创建一个可能是过度的,因为一旦迭代完成,你就会知道你必须删除它.所以你可以通过不使用smart_ptr... 来获得额外的记忆
单个内存泄漏可能会使您的产品及时发生故障(假设您的程序每小时泄漏4兆字节,打破计算机需要几个月的时间,然而,它会破坏,您知道因为漏洞存在) .
就像说"你的软件保证3个月,然后,叫我服务."
所以最后这真的是......你能处理这种风险吗?使用原始指针处理数百个不同对象的索引值得失去对内存的控制.
如果答案是肯定的,那么使用原始指针.
如果您甚至不想考虑它,那么这smart_ptr是一个好的,可行的,非常棒的解决方案.