将相同的指针发送到两个不同的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
}

如果有人尝试使用指针而不是Function调用shared_ptr,这将导致编译器出错。但这并不能阻止某人声明void Function(std::shared_ptr p),但是我认为这不太可能。

这还不好吗?有更好的方法吗?

最佳答案

解决方案很简单:首先不要让原始指针拥有自己的内存。此模式:

int* p = new int;
std::shared_ptr<int> p1(p);
std::shared_ptr<int> p2(p); // BAD

根本不应该存在。从您的代码库中消除它。在C++ 11中new合法的唯一地方是作为对智能指针的构造函数调用的参数(或在非常底层的东西中)。

IE。有这样的代码:
std::shared_ptr<int> p1(new int);

或者更好(不再涉及裸new):
auto p1 = std::make_shared<int>();

请注意,在代码中使用原始指针是可以的(但是我甚至对我所见过的大多数C++代码都提出了质疑)。但是,如果您使用原始指针,请不要让它们拥有内存。指向自动存储(无需资源管理),或者使用unique_ptr并通过其get成员函数访问原始指针。

09-10 00:06
查看更多