【发布时间】:2012-06-27 10:14:36
【问题描述】:
将相同的指针发送到两个不同的shared_ptr 是不好的,它会导致双重释放,如下所示:
int* p = new int;
std::shared_ptr<int> p1(p);
std::shared_ptr<int> p2(p); // BAD
你可以用std::enable_shared_from_this实现同样的目的:
class Good: public std::enable_shared_from_this<Good>
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
int main()
{
std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
}
但这仍然不能防止:
class Good: public std::enable_shared_from_this<Good>
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
int main()
{
Good* p = new Good;
std::shared_ptr<Good> gp3(p);
std::shared_ptr<Good> gp4(p); // BAD
}
如果你有这样的代码,这可能会成为一个问题:
void Function(std::shared_ptr<Good> p)
{
std::cout << p.use_count() << '\n';
}
int main()
{
Good* p = new Good;
std::shared_ptr<Good> p1(p);
Function(p); // BAD
}
当有智能指针时,为什么我要使用常规指针?因为在性能关键代码中(或为方便起见)shared_ptr 或weak_ptr 的开销是不可取的。
为了防止这个错误,我做了:
class CResource : public shared_ptr<Good>
{
public:
CResource()
{
}
CResource(std::shared_ptr<CBaseControl> c)
: CResource(c)
{
}
private:
CResource(CBaseControl* p)
{
}
};
void Function(CResource p)
{
std::cout << p.use_count() << '\n';
}
int main()
{
Good* p = new Good;
CResource p1(std::shared_ptr<Good>(p));
Function(p); // Error
}
如果有人试图用指针而不是shared_ptr 调用Function,这将导致编译器出错。但这并不能阻止某人声明void Function(std::shared_ptr p),但我认为这不太可能。
这仍然很糟糕吗?有更好的方法吗?
【问题讨论】:
-
“
shared_ptr或weak_ptr的开销是不可取的” 你真的可以量化这个开销吗?我参与了一个项目,该项目执行一些具有实时要求(例如帧速率)的大量图像处理工作,我们经常使用shared_ptr,因为 real 开销在其他地方算法。 -
但是你真的可以量化这个开销吗?您是否运行了基准测试并证明是的,
std托管指针的代价太高了?我认为您正在进行过早的优化。还是只是您不喜欢在使用时输入额外的调用来锁定每个weak_ptr? -
让我感到惊讶。我倾向于责怪您的系统架构,但从这里看不到。
-
您的 BAD 示例不应编译,shared_ptr 有一个
explicit构造函数,因此您无法将原始指针传递给采用shared_ptr的函数。正如康拉德的回答所说,只是不要以明显有风险的风格来写它。问题基本上是“如果我写好代码是安全的,如果我写坏代码就不是”。所以不要那样做。 -
@JorgeRodriguez:如果你使用
boost::intrusive_ptr,你可以获得原始指针的性能,因为它没有额外的间接级别。
标签: c++ c++11 shared-ptr