与裸指针相比,使用智能指针,尤其是 boost::shared_ptr 在时间和内存方面的成本更高?对游戏/嵌入式系统的性能密集型部分使用裸指针是否更好?您会建议对性能密集型组件使用裸指针还是智能指针?
6 回答
取消引用智能指针通常是微不足道的,当然对于发布模式的提升。所有 boost 检查都在编译时进行。(智能指针理论上可以跨线程执行智能操作)。这仍然留下了许多其他操作。Nicola 提到了建造、复制和破坏。不过,这不是完整的集合。其他重要的操作是交换、赋值和重置为 NULL。基本上,任何需要智能的操作。
请注意,其中一些操作被一些智能指针排除在外。例如boost::scoped_ptr
,甚至不能被复制,更不用说被分配了。由于这留下了更少的操作,因此可以针对这些更少的方法优化实现。
事实上,随着 TR1 的出现,编译器很可能使用智能指针比原始指针做得更好。例如,编译器可以证明智能不可复制指针在某些情况下没有别名,仅仅是因为它是不可复制的。想一想:当创建两个指向同一个对象的指针时,就会发生别名。如果第一个指针不能被复制,第二个指针怎么会指向同一个对象呢?(也有办法解决这个问题 - operator* 必须返回一个左值)
Boost 提供不同的智能指针。一般来说,内存占用(根据智能指针的种类而异)和性能应该不是问题。对于性能比较,您可以查看此http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/smarttests.htm。
正如你所看到的,在性能比较中只考虑了构造、复制和销毁,这意味着取消引用智能指针的成本应该与原始指针的成本相同。
shared_ptr<>
以下代码段演示了使用 a代替原始指针没有性能损失:
#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
。
它们结合了原始指针容器的性能和智能指针容器的便利性(即它们提供人们希望 STL 容器提供的功能std::auto_ptr
,如果可行的话)。