给定以下类型
// interface and implementation used in one part of the codebase
struct Image
{
virtual std::vector<uint8_t>& GetData () = 0;
};
struct VecImage : public Image
{
std::vector<uint8_t> mData;
std::vector<uint8_t>& GetData () { return mData; }
};
// used in another part of the codebase
struct PtrImage
{
std::shared_ptr<uint8_t> mData;
PtrImage (std::shared_ptr<Image> pIm);
};
以下构造函数是将 Image
转换为 PtrImage
的合理且正确的方法吗?
PtrImage::PtrImage (std::shared_ptr<Image> pIm)
{
struct im_deleter
{
std::shared_ptr<Image> keepAlive;
void operator () (uint8_t* ptr)
{
keepAlive.reset ();
}
};
mData = { &pIm->GetData()[0], im_deleter { pIm } };
}
PtrImage
用作“值类型”,它通过值传递,而 Image
仅在共享指针中传递。
最佳答案
is the following constructor a sane..
您延长 Image
的生命周期感谢析构函数,所以 data
仍然有效。
所以你在这一点上是正确的......
但是, vector 可能会重新分配,从而使缓冲区无效。
因此生成的代码是不安全的。
您可以存储std::shared_ptr<std::vector<uint8_t>> mData;
为了安全起见。
.. and correct way
我们有更好/更简单的别名构造函数 std::shared_ptr
:
struct PtrImage
{
std::shared_ptr<std::vector<uint8_t>> mData;
PtrImage (std::shared_ptr<Image> pIm) : mData(pIm, &pIm->GetData()) {}
};
所以所有权信息PtrImage::mData
与 pIm
共享.
注意:我假设 GetData()
返回 vector 具有与 Image
相同(或更长)的生命周期(至于VecImage
)。如果它是一个不相关的 vector (来自其他对象),那么你将没有解决方案。
正如评论中所述, vector 也不应该重新分配
关于c++ - 你可以使用deleter的成员来保持shared_ptr的事件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56164162/