2

假设我们有以下代码

class Image
{
public:
    Image(const std::string & path)
    {
        pBitmap_ = FreeImage_Load( imageFormat, pathname.c_str() );
    }
    ~Image()
    {
        FreeImage_Unload(pBitmap_);
    }
private:
    FIBITMAP * pBitmap_;

};

Image(Image && rhs) 将如何实现?移动 dtor 后仍然在 rhs 上调用,这不会产生预期的效果?我想像

Image::Image( Image && rhs )
{
    pBitmap_ = std::move(rhs.pBitmap_);
            rhs.pBitmap_ = nullptr;
}

然后在 dtor 中检查 null 应该可以解决问题,但是有更好的方法吗?

4

1 回答 1

6

解决方案是不要自己做,而是使用语言的库设施:

struct FiBitmapDeleter {
    void operator()(FIBITMAP *pBitmap) { FreeImage_Unload(pBitmap); }
};

class Image {
private:
    std::unique_ptr<FIBITMAP, FiBitmapDeleter> pBitmap_;
};

现在您不需要编写析构函数、移动构造函数或移动赋值运算符。此外,您的类会自动删除其复制构造函数和复制赋值运算符,因此您也无需担心这些,完成五法则。

另一种方法是 specialize default_delete,这意味着您不需要将删除器类型提供给unique_ptr

namespace std {
    template<> struct default_delete<FIBITMAP> {
        void operator()(FIBITMAP *pBitmap) { FreeImage_Unload(pBitmap); }
    };
}
std::unique_ptr<FIBITMAP> pBitmap_;

这具有全局影响,因此只有当您确信您的代码是程序中唯一可能执行此专业化的代码时,您才应该这样做。

于 2012-11-08T15:58:57.650 回答