【发布时间】:2008-11-21 11:24:55
【问题描述】:
与裸指针相比,使用智能指针,尤其是 boost::shared_ptr 在时间和内存方面的成本要高多少?对游戏/嵌入式系统的性能密集型部分使用裸指针是否更好?您会建议对性能密集型组件使用裸指针还是智能指针?
【问题讨论】:
标签: c++ boost smart-pointers
与裸指针相比,使用智能指针,尤其是 boost::shared_ptr 在时间和内存方面的成本要高多少?对游戏/嵌入式系统的性能密集型部分使用裸指针是否更好?您会建议对性能密集型组件使用裸指针还是智能指针?
【问题讨论】:
标签: c++ boost smart-pointers
取消引用智能指针通常是微不足道的,当然对于发布模式的提升。所有 boost 检查都在编译时进行。 (智能指针理论上可以跨线程执行智能操作)。这仍然留下了许多其他操作。 Nicola 提到了建造、复制和破坏。不过,这不是完整的集合。其他重要的操作是交换、赋值和重置为 NULL。基本上,任何需要智能的操作。
请注意,其中一些操作被一些智能指针排除在外。例如。 boost::scoped_ptr 甚至不能被复制,更不用说被分配了。由于这留下了更少的操作,因此可以针对这些更少的方法优化实现。
事实上,随着 TR1 的出现,编译器很可能使用智能指针比原始指针做得更好。例如。编译器可能会证明智能不可复制指针在某些情况下没有别名,仅仅是因为它是不可复制的。想一想:当创建两个指向同一个对象的指针时,就会发生别名。如果第一个指针不能被复制,那么第二个指针怎么会指向同一个对象呢? (也有一些方法可以解决这个问题 - operator* 必须返回一个左值)
【讨论】:
Boost 提供不同的智能指针。一般来说,内存占用(根据智能指针的种类而异)和性能应该不是问题。如需性能比较,您可以查看此http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/smarttests.htm。
正如您所见,性能比较只考虑了构造、复制和销毁,这意味着取消引用智能指针的成本应该与原始指针的成本相同。
以下 sn-p 表明使用 shared_ptr<> 代替原始指针不会降低性能:
#include <iostream>
#include <tr1/memory>
int main()
{
#ifdef USE_SHARED_PTR
std::tr1::shared_ptr<volatile int> i(new int(1));
#else
volatile int * i = new int(1);
#endif
long long int h = 0;
for(long long int j=0;j < 10000000000LL; j++)
{
h += *i;
}
std::cout << h << std::endl;
return 0;
}
【讨论】:
处理性能问题的唯一方法是分析您的代码。无论如何,性能问题的最大部分是想象的;只有分析才能向您指出瓶颈所在。
如果事实证明使用智能指针会产生原始指针不会产生的瓶颈,请使用原始指针!在那之前,我不会太担心它;大多数对智能指针的操作都相当快。您可能过于频繁地比较字符串(或类似的东西),以至于它们并不重要。
【讨论】:
引用计数智能指针(最常见的类型)只会在您复制、创建和删除它们时花费更多。如果您要进行大量复制,这种额外的成本可能会很大,因为它们中的大多数都是线程安全的。
如果您只想要一个“自动删除”指针,那么可以使用备受诟病的 auto_ptr,或者来自 C++0x 的新的、闪亮的(但还没有太多支持的)unique_ptr。
【讨论】:
当我上次使用 VC6 进行测试时,编译器无法像使用原始指针那样优化使用智能指针的代码。从那以后情况可能会发生变化。
【讨论】:
在“手动”管理的std::vector<T*>(即原始指针)和std::vector<boost::shared_ptr<T> > 之间有一个经常被忽视的中间点,其形式为boost::ptr_container 类。
它们结合了原始指针容器的性能和智能指针容器的便利性(即它们提供了人们希望std::auto_ptr 的 STL 容器提供的功能,if that worked)。
【讨论】: