我是C++业余。我写一些Win32API码和有把手和古怪的复合分配的对象大量.所以我想知道-还有某些包装类,这将使资源管理更容易?

例如,当我想到负荷的一些数据我打开一个文件 CreateFile() 并得到一个 HANDLE.当我完成它,我应该叫 CloseHandle() 上。但是对于任何合理的复杂的装载功能会有几十个可能的出口点,更不要说例外情况。

因此,这将是巨大的,如果我能包裹处理某些种类的包装类,这将自动呼叫 CloseHandle() 一旦执行留的范围。甚至更好的-它可以做一些基准计算,因此我可以通过它在其他功能,并将释放的资源只有当最后的参考留的范围。

这个概念很简单-但是不是有什么样的标准图书馆?我使用Visual Studio2008年,通过这种方式,我不要附加一个第3方框架等提高或什么的。

有帮助吗?

解决方案

写你自己的。这只是几行代码。这只是这样一个简单的任务,它不是的值得的提供一个通用的可重复使用的版本。

struct FileWrapper {
  FileWrapper(...) : h(CreateFile(...)) {}
  ~FileWrapper() { CloseHandle(h); }

private:
  HANDLE h;
};

想想仿制药必须做的:它不得不被参数化的,所以你可以指定的任何的对函数和的任何的若干参数他们。只是实例化这样的对象可能会采取的码一样多的行作为上述类定义。

当然,C ++ 0X可能通过添加lambda表达式的稍微打破平衡。两个lambda表达式可以很容易地传递给普通的包装类,所以一旦的C ++ 0x支持,恶有恶报,我们的可能的看到这样一个通用的RAII类中添加,以提高或东西。

但此刻,它更容易当你需要它刚刚推出自己的。

作为添加引用计数,我建议反对。引用计数是昂贵的(突然你的手柄,必须动态地分配和引用计数器必须保持在每一个任务),并且很难得到正确的。这只是微妙的竞争条件在多线程环境爆破的区域。

如果您的的需要引用计数,只是这样做boost::shared_ptr<FileWrapper>:包裹在shared_ptr您的自定义的ad-hoc RAII类

其他提示

基本上,fstream是一个很好的C ++包装器文件句柄。它的,这意味着它是便携式的,很好的测试,且可扩展的面向对象的方式的标准的一部分。对于文件资源,这是一个很大的概念。

然而,fstream仅适用于文件,而不是通用的手柄,即线程,进程,同步对象,存储器映射文件等

这些包装被称为ATL。

如果你的处理是一个事件或者类似,使用 CHandle 类。

如果你的处理是一个文件,使用CAtlFile源之一,它包Api样调用和ReadFile.

还有其他有用的包装在ATL CAtlFileMapping<T> 是RAII包装在存储器映文件, CPath 包裹shell32APIs对于路径处理,等等。

ATL是大型图书馆,但是,低层的东西,如文件,符和集合是孤立的。你可以用它们在所有Win32应用程序。是头只是,你不需要任何东西,或者发布额外Dll像MFC或CRT,代码汇编成WinAPI呼吁,只是工作。

他们拆分从MFC在VS2003或2005年不记得,即Visual Studio2008肯定有他们。有一个警告然而,如果您使用的免费软件版本较高,必须在2015年或更新的。

下面是一个“通过C / C ++视窗”关基于从所述EnsureCleanup代码: http://www.codeproject.com/KB/cpp/template2003.aspx

MFC有一些合适的原语(看的CFile 例如),而不是标准库。

视觉C ++ 2008支持TR1通过功能包,并且TR1包括shared_ptr的。我会用这个 - 这是一个非常强大的智能指针类,并可以推广到做资源管理你所要求的类型

TR1是一个有效的扩展标准。我相信这是官方还是“准标准”,但有效的话,可以考虑它锁定了。

我不认为有在标准库什么,我也怀疑共享指针(如在升压)可用于(因为这些会期望指针处理,不处理)。

它不应该是很难自己写一个,继范围卫成语(和利用的模板/函数指针等等,如果你选择)。

template <typename Traits>
class unique_handle
{
    using pointer = typename Traits::pointer;

    pointer m_value;

    auto close() throw() -> void
    {
        if (*this)
        {
            Traits::close(m_value);
        }
    }

public:

    unique_handle(unique_handle const &) = delete;
    auto operator=(unique_handle const &)->unique_handle & = delete;

    explicit unique_handle(pointer value = Traits::invalid()) throw() :
        m_value{ value }
    {
    }

    unique_handle(unique_handle && other) throw() :
        m_value{ other.release() }
    {
    }

    auto operator=(unique_handle && other) throw() -> unique_handle &
    {
        if (this != &other)
        {
            reset(other.release());
        }

        return *this;
    }

    ~unique_handle() throw()
    {
        close();
    }

    explicit operator bool() const throw()
    {
        return m_value != Traits::invalid();
    }

    auto get() const throw() -> pointer
    {
        return m_value;
    }

    auto get_address_of() throw() -> pointer *
    {
        ASSERT(!*this);
        return &m_value;
    }

    auto release() throw() -> pointer
    {
        auto value = m_value;
        m_value = Traits::invalid();
        return value;
    }

    auto reset(pointer value = Traits::invalid()) throw() -> bool
    {
        if (m_value != value)
        {
            close();
            m_value = value;
        }

        return static_cast<bool>(*this);
    }

    auto swap(unique_handle<Traits> & other) throw() -> void
    {
        std::swap(m_value, other.m_value);
    }
};

template <typename Traits>
auto swap(unique_handle<Traits> & left,
    unique_handle<Traits> & right) throw() -> void
{
    left.swap(right);
}

template <typename Traits>
auto operator==(unique_handle<Traits> const & left,
    unique_handle<Traits> const & right) throw() -> bool
{
    return left.get() == right.get();
}

template <typename Traits>
auto operator!=(unique_handle<Traits> const & left,
    unique_handle<Traits> const & right) throw() -> bool
{
    return left.get() != right.get();
}

template <typename Traits>
auto operator<(unique_handle<Traits> const & left,
    unique_handle<Traits> const & right) throw() -> bool
{
    return left.get() < right.get();
}

template <typename Traits>
auto operator>=(unique_handle<Traits> const & left,
    unique_handle<Traits> const & right) throw() -> bool
{
    return left.get() >= right.get();
}

template <typename Traits>
auto operator>(unique_handle<Traits> const & left,
    unique_handle<Traits> const & right) throw() -> bool
{
    return left.get() > right.get();
}

template <typename Traits>
auto operator<=(unique_handle<Traits> const & left,
    unique_handle<Traits> const & right) throw() -> bool
{
    return left.get() <= right.get();
}

struct null_handle_traits
{
    using pointer = HANDLE;

    static auto invalid() throw() -> pointer
    {
        return nullptr;
    }

    static auto close(pointer value) throw() -> void
    {
        VERIFY(CloseHandle(value));
    }
};

struct invalid_handle_traits
{
    using pointer = HANDLE;

    static auto invalid() throw() -> pointer
    {
        return INVALID_HANDLE_VALUE;
    }

    static auto close(pointer value) throw() -> void
    {
        VERIFY(CloseHandle(value));
    }
};

using null_handle = unique_handle<null_handle_traits>;
using invalid_handle = unique_handle<invalid_handle_traits>;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top