通过放置 new 转移对象所有权
我有一个 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
I have a Visual Studio 2008 C++ project with a class that manages a resource that cannot be copied. I have implemented transfer-by-reference-structure semantics (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
Unfortunately, when I use this pattern with a library that uses placement-new, I get a compiler error:
.\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
]
For example:
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;
}
How can I modify Test
such that it can be used with placement new and still retain its ownership semantics?
Thanks,
PaulH
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
关注
main
函数,因为它应该表明你想要的语义,有两个大问题:首先,你没有分配内存,这意味着如果编译器处理代码,就会导致 UB (会尝试在放置新操作中通过NULL
地址调用Test
的构造函数。另一个问题对于
std::auto_ptr< 的用户来说是众所周知的/code>:复制构造函数的签名采用非 const 引用,这意味着您无法在 const 对象上调用它;另一方面,您尝试在
Copy
模板中调用承诺的复制构造函数。不要更改第二个参数引用的对象:最后,我不确定是否由于复制到问题中,但我不确定您一开始提供的引用包装器类的意图是什么,所以您可能想澄清一下。
Focusing on the
main
function, as that should indicate your intended semantics, there are two big problems: First, you are not allocating memory, which means that if the compiler would process the code, it would cause UB (would try to call the constructor ofTest
over theNULL
address in the placement new operation.The other issue is well known to users of
std::auto_ptr
: The signature of the copy constructor takes a non-const reference, and that means that you cannot call it on a const object. On the other end you are trying to call the copy constructor inside theCopy
template that promised not to change the object referenced by the second argument:Finally, I am not sure if due to copying into the question, but I am not sure of what your intentions are with the reference wrapper class that you are providing in the beginning, so you might want to clarify.
您的问题与新的放置无关。在
void Copy
中,您尝试复制 Test 类型的对象,但您不允许复制。这就是问题所在。另外,您尝试将 new 放置在 NULL 上。您未能正确实现该结构,因为常量运算符 test_ref() 永远不会被调用,因为您采用了 const T& 并且它是非常量运算符。这意味着,除非你想在人们认为应该是副本时用动作给他们带来惊喜,否则你不能这样做。Your problem has nothing to do with placement new. In
void Copy
then you attempted to copy an object of type Test, but you disallow copying. That's the problem. Also, you attempted to placement new on NULL. You failed to implement the structure properly because of the constness-operator test_ref()
can never be called because you took aconst T&
and it's a non-const operator. This means that unless you want to surprise people with moves when they think it should be copies, you cannot do this.