【发布时间】:2011-05-16 22:18:15
【问题描述】:
我有一个 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 一起使用并且仍然保留其所有权语义?
谢谢, 保罗H
【问题讨论】:
-
避免名称以双下划线开头,因为这些名称是为实现保留的(编译器+标准库)。此外,从
Test *p = NULL;到Test *p = new Test();的更改并不能解决未定义的行为,它只是将其换成另一个(它是 UB 两次构造相同的对象,在您的代码中,您分配内存并调用main中的构造函数,然后在Copy中再次调用构造函数(并且永远不会破坏或释放内存......)
标签: c++ ownership placement-new