如何在处理C库对象时实现std :: move()

时间:2012-11-08 15:45:57

标签: c++ c++11 move-semantics

假设我们有以下代码

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应该可以解决问题,但是有更好的方法吗?

1 个答案:

答案 0 :(得分:6)

解决方案是不能自己动手,但使用该语言的库设施:

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

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

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

另一种方法是专门化default_delete,这意味着您不需要向unique_ptr提供删除类型:

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

这具有全局效果,所以只有当您确信自己是程序中可能执行此专业化的唯一代码时,才应该这样做。