通过放置 new 转移对象所有权

发布于 2024-11-07 19:02:25 字数 1668 浏览 0 评论 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,以便它可以与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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

纸短情长 2024-11-14 19:02:25

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

另一个问题对于 std::auto_ptr< 的用户来说是众所周知的/code>:复制构造函数的签名采用非 const 引用,这意味着您无法在 const 对象上调用它;另一方面,您尝试在 Copy 模板中调用承诺的复制构造函数。不要更改第二个参数引用的对象:

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

最后,我不确定是否由于复制到问题中,但我不确定您一开始提供的引用包装器类的意图是什么,所以您可能想澄清一下。

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 of Test over the NULL 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 the Copy template that promised not to change the object referenced by the second argument:

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

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.

盛夏尉蓝 2024-11-14 19:02:25

您的问题与新的放置无关。在 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 a const 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文