winapi - 使大量分配在第一次接触时自动提交

标签 winapi unmanaged

如何在 Windows 中分配内存但直到第一次触摸才提交它?

我看到 VirtualAlloc 允许我保留一定范围的内存,但我需要在使用前手动提交该内存的部分。我希望在我第一次引用它时自动提交。

此外,如果可能的话,我不希望在提交之前将内存归零。

(顺便说一句,这可以在 Linux 上通过设置/dev/zero block 的私有(private)内存映射来完成)

最佳答案

您可以使用自己设计的智能指针,它会在第一次解引用时提交它(当然是通过重载解引用和间接运算符)。

这是一个示例智能指针,它在第一次取消引用(惰性实例化)时创建给定对象的实例。同样的想法,基本上:

template <typename T>
struct default_constructor_factory
{
    T * operator ()() { return new T; }
};

template <typename T, typename F = default_constructor_factory<T> >
class lazy_ptr : boost::noncopyable
{
public:
    typedef T element_type;
    typedef T value_type;
    typedef F factory_type;
    typedef lazy_ptr<T,F> this_type;

    lazy_ptr() : m_ptr(), m_factory() { }
    lazy_ptr(F factory) : m_ptr(), m_factory(factory) { }
    ~lazy_ptr() { if (m_ptr != NULL) delete m_ptr; }

    T & operator* () const
    {
        return *get();
    }

    T * operator-> () const
    {
        return get();
    }

    T * get() const
    {
        if (m_ptr == NULL)
            m_ptr = m_factory();
        return m_ptr;
    }

    void reset(T * p)
    {
        if (p != m_ptr)
        {
            if (m_ptr != NULL)
                delete m_ptr;
            m_ptr = p;
        }
    }

    T * release()
    {
        T * p = m_ptr;
        m_ptr = NULL;
        return p;
    }

    // non-dereferencing accessors

    T * peek() const
    {
        // may return NULL
        return m_ptr;
    }

    bool dereferenced() const
    {
        return peek() != NULL;
    }

//  operator bool() const { return dereferenced(); }

    // handle intrinsic conversion to testable bool using unspecified_bool technique
    typedef T * this_type::*unspecified_bool_type;
    operator unspecified_bool_type() const // never throws
    {
        return dereferenced() ? &this_type::m_ptr : NULL;
    }

private:
    // we must remain it's only owner!
    mutable T * m_ptr;

    // our factory generates the needed element on-demand
    mutable factory_type m_factory;
};

// shared_lazy_ptr
//
// we act as a copyable lazy pointer
// essentially, we add reference counting to a single shared lazy pointer
//
template <typename T, typename F = default_constructor_factory<T> >
class shared_lazy_ptr
{
public:
    typedef T element_type;
    typedef T value_type;
    typedef F factory_type;
    typedef lazy_ptr<T,F> ptr_type;
    typedef shared_lazy_ptr<T,F> this_type;

    shared_lazy_ptr() : m_ptr(new ptr_type) { }
    shared_lazy_ptr(F factory) : m_ptr(new ptr_type(factory)) { }

    // copy ctor
    shared_lazy_ptr(const this_type & rhs) : m_ptr(rhs.m_ptr), m_references(rhs.m_references) { }

    // assignment
    this_type & operator = (const this_type & rhs)
    {
        if (m_references.Reattach(rhs.m_references))
            delete m_ptr;
        m_ptr = rhs.m_ptr;
        return *this;
    }

    ~shared_lazy_ptr() 
    {
        if (m_references.IsOnly())
            delete m_ptr;
    }

    T & operator* () const
    {
        return *get();
    }

    T * operator-> () const
    {
        return get();
    }

    T * get() const
    {
        return m_ptr->get();
    }

    void reset(T * p)
    {
        if (p != get())
        {
            if (m_ptr != NULL)
                delete m_ptr;
            m_ptr = p;
        }
    }

    // non-dereferencing accessors

    T * peek() const
    {
        // may return NULL
        return get()->peek();
    }

    bool dereferenced() const
    {
        return peek() != NULL;
    }

//  operator bool() const { return dereferenced(); }

    // handle intrinsic conversion to testable bool using unspecified_bool technique
    typedef T * this_type::*unspecified_bool_type;
    operator unspecified_bool_type() const // never throws
    {
        return dereferenced() ? &this_type::m_ptr : NULL;
    }

private:
    lazy_ptr<T, F> * m_ptr;         // shared *lazy* pointer to the actual object
    ReferenceCount m_references;    // shared reference count to our lazy pointer
};

关于winapi - 使大量分配在第一次接触时自动提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4597403/

相关文章:

c# - 在非托管 C++ DLL 和托管 C# UI 之间发送信息

c# - 固定托管 List<> 以获取指向数据的指针

.NET - 从非托管阵列复制到非托管阵列

powershell - 将两个管道值加在一起

c++ - 将位图加载到窗口

c - 进程内部/外部生成的不同内存转储

java - 使用 UnmanagedExports 和 JNA 将字节数组从 C# 返回到 Java

c++ windows通过USB串行获取USB端口和集线器

winapi - LoadLibrary 失败并且依赖遍历器没有帮助

c# - 将托管字符串编码(marshal)到字符指针 c#