Search code examples
c++-clioperator-overloadingcopy-constructorcautoptr

AutoPtr in C++/CLI mixed mode


I have a C++/CLI wrapper around native .lib and .h files. I use the AutoPtr class pretty extensively in the wrapper class to manage the unmanaged objects I create for wrapping. I have hit a roadblock with the copy constructor/assignment operator.

Using the AutoPtr class from Mr. Kerr: http://weblogs.asp.net/kennykerr/archive/2007/03/26/AutoPtr.aspx

He suggests the following(in the comments) to recreate the behavior of the assignment operator:

SomeManagedClass->NativePointer.Reset(new NativeType);

Which I believe is true. But when I compile my code:

ByteMessageWrap (const ByteMessageWrap% rhs)
{
     AutoPtr<ByteMessage> m_NativeByteMessage(rhs.m_NativeByteMessage.GetPointer());
};

ByteMessageWrap% operator=(const ByteMessageWrap% rhs)
{
     //SomeManagedClass->NativePointer.Reset(new NativeType);
     if (this == %rhs) // prevent assignment to self
        return *this;

     this->m_NativeByteMessage.Reset(rhs.m_NativeByteMessage.GetPointer());
     return *this;
};

-- I get the following errors:

error C2662: 'WrapTest::AutoPtr::GetPointer' : cannot convert 'this' pointer from 'const WrapTest::AutoPtr' to 'WrapTest::AutoPtr %'

Has anyone experienced similar issues?


For further background on the answer, I removed the "const" keyword from the signature. I know that is not smiled upon in terms of code correctness for a copy ctor, but the CLR doesn't like it at all -- sort of belies the CLR at its core with memory management.

I wonder if it's possible to leave the const in the signature and then use GCHandle or pin_ptr to make sure memory doesn't move on you while performing the copy?


Solution

  • Looking at Kenny Kerr's AutoPtr, it transfers ownership in its constructor -- essentially a "move" constructor rather than a copy constructor. This is analogous with std::auto_ptr.

    If you really want to transfer ownership from rhs to this (i.e. leave rhs without it NativeByteMessage), you need to change your copy ctor into a move ctor.

    Also, you need to use initialization syntax;

    // warning - code below doesn't work
    ByteMessageWrap (ByteMessageWrap% rhs)
        : m_NativeByteMessage(rhs.m_NativeByteMessage); // take ownership
    {
    }
    
    ByteMessageWrap% operator=(ByteMessageWrap% rhs)
    {
         //SomeManagedClass->NativePointer.Reset(new NativeType);
         if (this == %rhs) // prevent assignment to self
            return *this;
    
         m_NativeByteMessage.Reset(rhs.m_NativeByteMessage.Release());
         return *this;
    }