我有一个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
以使其可以与placement new一起使用并仍然保留其所有权语义?
谢谢, PaulH
答案 0 :(得分:1)
关注main
函数,因为它应该表明你的预期语义,有两个大问题:首先,你没有分配内存,这意味着如果编译器将处理代码,它将导致UB (会尝试在展示位置新操作中的Test
地址上调用NULL
的构造函数。
另一个问题是std::auto_ptr
的用户所熟知的:复制构造函数的签名采用非const引用,这意味着你不能在const对象上调用它。另一方面,您试图在{em>承诺的Copy
模板中调用复制构造函数,而不是更改第二个参数引用的对象:
template <typename T>
void Copy( T* p, T& o ) {
new (p) T( o ); // would work, object is non-const
}
最后,我不确定是否由于复制到问题中,但我不确定你在开头提供的参考包装类的意图是什么,所以你可能想澄清一下。
答案 1 :(得分:0)
您的问题与放置新内容无关。在void Copy
中,您尝试复制Test类型的对象,但不允许复制。那就是问题所在。此外,您尝试将新位置放在NULL上。你没有正确实现结构,因为constness- operator test_ref()
永远不会被调用,因为你使用了const T&
并且它是一个非const运算符。这意味着,除非你想让那些认为应该是副本的人感到惊讶,否则你不能这样做。