请考虑一些包含_sku
(例如struct成员)的数据源。如果您保证它不是一个临时值,但在当前范围内将是有效的,并且您希望对该指针使用别名:哪个性能更好,请复制shared_ptr
或使用(可能是const)参考原著吗?
示例:
shared_ptr
编辑:动机。例如,当1)获取struct S {
shared_ptr<T> ptr;
};
void fun(S s) {
shared_ptr<T> alias1 = s.ptr;
shared_ptr<T> const& alias2 = s.ptr;
/* do something with the alias */
}
涉及遍历一连串的函数调用或derefs或2)希望提高可读性。
权衡。从某种意义上说,复制指针看起来更“正确”,因为它模仿了您对原始指针的处理方式,但是它需要refcount机制来完成其工作(在构造和销毁方面) )。另一方面,拥有一个您可能经常使用的引用会导致额外的取消引用,这反过来又会很昂贵(该引用是您对保存的s.ptr
对象所做的任何事情的基础)。
有一个通用的经验法则是什么更有效?
答案 0 :(得分:2)
在不拥有所有权的情况下修改或操作数据的算法应作用于对数据(或其容器)的迭代器或引用。
例如,如果要查找一堆值的平均值,则应编写一个将迭代器带到值集的函数(或通过const引用获取容器)。您不应该要做的是通过副本传递矢量,或传递智能指针。
复制shared_ptr
会产生开销,算法本身应该始终希望它们处理的数据超过计算的寿命。
何时使用shared_ptr
? shared_ptr
在编写容器或其他需要在一段未知时间内保留一条数据的类时使用。对象拥有所有权,而不是功能,而不是算法。 (当然,成员函数可以接受shared_ptr
作为输入,但是只有在它们所需要的类不需要这些数据的情况下,这样做才有意义)。
线程是该经验法则的例外。如果要启动新线程,则绝对应该按值传递任何shared_ptr
。该线程可能存在一段未知的时间,您需要确保它有权访问的任何数据在线程退出之前一直有效。
复制shared_ptr
比开始启动线程要便宜得多,因此开销很小。
答案 1 :(得分:0)
高级Perez关于使用共享指针的最佳方法是正确的。
如果完全使用它们,则应明智地使用它们,以增加 在大多数编译器中,引用计数是一项非常昂贵的工作。
在我开发的一款引人注目的游戏中,大部分帧时间都占用了一个共享指针取消引用。
在位掩码给出的示例中,结构本身是通过值传递的,由于复制删除或类似的优化,它显然不如听起来那样糟糕。
What are copy elision and return value optimization?
如果不幸遇到了使用共享指针的麻烦,则可以使用get()将其转换为常规指针。
当然,这会使代码的安全性降低,但是谁想要无聊的生活:)
#include <memory>
struct S {
std::shared_ptr<int> ptr;
};
void fun(S s) {
int *alias = s.ptr.get();
*alias = 1;
}
Godbolt:
fun(S): # @fun(S)
mov rax, qword ptr [rdi]
mov dword ptr [rax], 1
ret