0

我有一个 Visual Studio 2008 C++ 项目,其中有一个类管理无法复制的资源。我已经实现了按引用结构传输的语义(ala std::auto_ptr)。

class Test;

struct Test_Ref
{
    Test& ref_;
    Test_Ref( Test& t ) : ref_( t ) { };
private:
    Test_Ref& operator=( Test_Ref const& );
}; // struct Test_Ref

class Test
{
public:
    explicit Test( int f = 0 ) : foo_( f ) { };

    Test( Test& other ) : foo_( other.Detach() ) { };

    Test& operator=( Test& other )
    {
        foo_ = other.Detach();
        return *this;
    };

    Test( Test_Ref other ) : foo_( other.ref_.Detach() ) { };

    Test& operator=( Test_Ref other )
    {
        foo_ = other.ref_.Detach();
        return *this;
    };

    operator Test_Ref() { return Test_Ref( *this ); };

private:

    int Detach()
    {
        int tmp = foo_;
        foo_ = 0;
        return tmp;
    };

    // resource that cannot be copied. 
    int foo_;
}; // class Test

不幸的是,当我将此模式与使用placement-new 的库一起使用时,我得到一个编译器错误:

.\test.cpp(58) : error C2558: class 'Test' : no copy constructor available or copy constructor is declared 'explicit'
    .\test.cpp(68) : see reference to function template instantiation 'void Copy<Test>(T *,const T &)' being compiled
    with
    [
        T=Test
    ]

例如:

template< class T > inline void Copy( T* p, const T& val ) 
{
    new( p ) T( val );
}

int _tmain( int /*argc*/, _TCHAR* /*argv*/[] )
{
    Test* __p = new Test();
    Test __val;
    Copy( __p, __val );
    return 0;
}

我怎样才能修改Test它以便它可以与放置 new 一起使用并且仍然保留它的所有权语义?

谢谢,保罗

4

2 回答 2

1

专注于main函数,因为这应该表明您的预期语义,有两个大问题:首先,您没有分配内存,这意味着如果编译器会处理代码,则会导致UB(会尝试调用构造函数在放置新操作中Test的地址。NULL

另一个问题是用户所熟知的std::auto_ptr:复制构造函数的签名采用非常量引用,这意味着您不能在 const 对象上调用它。另一方面,您试图在Copy模板中调用复制构造函数,该构造函数承诺不会更改第二个参数引用的对象:

template <typename T>
void Copy( T* p, T& o ) {
   new (p) T( o );         // would work, object is non-const
}

最后,我不确定是否由于复制到问题中,但我不确定您对一开始提供的参考包装类的意图是什么,因此您可能想澄清一下。

于 2011-05-16T22:29:27.760 回答
0

您的问题与安置新无关。然后,void Copy您尝试复制 Test 类型的对象,但您不允许复制。那就是问题所在。此外,您尝试将 new 放置在 NULL 上。由于 constness- 无法正确实现结构,因为您使用了 a并且它是一个非常量运算符,所以operator test_ref()永远无法调用该结构。const T&这意味着除非你想在人们认为应该是复制品时用动作让他们感到惊讶,否则你不能这样做。

于 2011-05-16T22:23:55.410 回答