将相同的指针发送到两个不同的 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)
,但我认为这不太可能。
这还很糟糕吗?有更好的方法吗?
最佳答案
解决方案很简单:从一开始就不要让原始指针拥有自己的内存。这种模式:
int* p = new int;
std::shared_ptr<int> p1(p);
std::shared_ptr<int> p2(p); // BAD
根本不应该存在。从您的代码库中消除它。 new
在 C++11 中唯一合法的地方是作为对智能指针的构造函数调用的参数(或者在非常低水平的东西)。
即有这样的代码:
std::shared_ptr<int> p1(new int);
或者更好(不再涉及裸new
):
auto p1 = std::make_shared<int>();
请注意,在代码中使用原始指针没有问题(但在我见过的大多数 C++ 代码中,我什至会质疑这一点)。但是如果你使用原始指针,不要让它们拥有内存。指向自动存储(无需资源管理)或使用 unique_ptr
并通过其 get
成员函数访问原始指针。
关于c++ - 防止多个 shared_ptr 指向同一个对象的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11223895/