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

标签 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) 是如何实现的? move dtor 后仍然在 rhs 上调用,这不会产生预期的效果? 我想是这样的

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

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

最佳答案

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

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

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

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

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

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

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

关于c++ - 处理 C 库对象时如何实现 std::move(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13292432/

相关文章:

c++ - 是否可以实现 std::move-and-clear 函数?

c++ - 关于 std::move 行为

rust - 如何在不引入新范围的情况下结束对对象的借用?

c++ - 当基类不包含数据成员时是否仍然需要虚拟继承?

c++ - 如何将可变参数传递给虚函数

c++ - 声明为返回 int 的函数不返回任何内容。这是未定义的行为吗?

c++ - 函数对象转换为函数指针

c++ - 为什么不能在 lambda 中使用私有(private)方法?

C++11类成员初始化

android - JNI 检测到应用程序错误 : can't call void android. graphics.Canvas.drawBitmap