Automatic generated move operations and raw pointe

2019-04-16 20:11发布

Consider a MemoryMappedFile class, with the following data members:

class MemoryMappedFile
{
....
private:
    // RAII wrapper to some OS-specific raw handle (e.g. Win32 HANDLE),
    // representing the memory-mapped file.
    Handle m_handle;

    // Pointer to file begin (first file byte).
    BYTE* m_first;

    // Pointer to file end (one byte past last file byte).
    BYTE* m_last;
};

The Handle class is some RAII wrapper to some specific OS raw C-like handle (e.g. think of Win32 HANDLE). It is not copyable, but it is movable.
Instead, m_first and m_last are raw pointers inside the memory area mapped with the file content.

I'd like the MemoryMappedFile class to be movable (but not copyable, just like the Handle class).

If it weren't for the raw pointers, according to C++11's rules of automatic generation of move constructor by member-wise moves, the class would be automatically movable.

Unfortunately, the raw pointers force me to write a custom move constructor:

MemoryMappedFile::MemoryMappedFile(MemoryMappedFile&& other)
    : m_handle( std::move(other.m_handle) )
{
    // Move m_first
    m_first = other.m_first;
    other.m_first = nullptr;

    // Move m_last
    m_last = other.m_last;
    other.m_last = nullptr;
}

It would be nice if C++ standard library had some form of "dumb-as-opposed-to-smart but movable" pointer, with zero-overhead, just like raw pointers (which are fine as observing non-owning pointers), but with move operations (move constructor and move assignment) defined, such that the compiler can automatically generate correct move operations in classes that have these pointers as data members.

Is there something like this in C++ standard library, or in Boost?

Or is there any other way to achieve the same goal (beside writing my own custom ObservingPointer class, wrapping raw pointers and defining move operations)?

2条回答
Summer. ? 凉城
2楼-- · 2019-04-16 20:37

Just use a std::unique_ptr with your own noop_deleter.

查看更多
在下西门庆
3楼-- · 2019-04-16 20:51

I frequently need a "smart" pointer that is both copyable and movable, but has a well-defined moved-from state, so I wrote tidy_ptr which is a "dumb" smart pointer that does nothing special except zero itself on move. That type is copyable, so to get the semantics you want for your class you would still need to define the copy operations as deleted (or just use std::unique_ptr with a no-op deleter).

I've tried to convince the standards committee that observer_ptr, "the world's dumbest smart pointer", should have this behaviour, but the consensus was that it should behave just like a built-in pointer (except for zero-initialization in the constructor). I still think it should zero on move. That paper shows a non_owning_ptr which is an alias for unique_ptr with a no-op deleter, which does what you want.

查看更多
登录 后发表回答