0

コピーできないリソースを管理するクラスを持つVisualStudio2008C++プロジェクトがあります。参照構造による転送セマンティクス(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新しい配置で使用でき、所有権のセマンティクスを保持できるように変更するにはどうすればよいですか?

ありがとう、PaulH

4

2 に答える 2

1

関数に焦点を当てると、main意図したセマンティクスを示すはずなので、2つの大きな問題があります。1つは、メモリを割り当てていないことです。つまり、コンパイラがコードを処理すると、UBが発生します(のコンストラクタを呼び出そうとします)。配置の新しい操作でアドレスをTest超えます。NULL

もう1つの問題は、次のユーザーによく知られていますstd::auto_ptr。コピーコンストラクターの署名は非const参照を取ります。つまり、constオブジェクトで呼び出すことはできません。もう一方の端では、2番目の引数によって参照されるオブジェクトを変更しないことを約束し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タイプのオブジェクトをコピーしようとしましたが、コピーを許可していません。それが問題です。また、NULLに新しい配置を試みました。constnessのために構造を適切に実装できませんでした-を取得し、それが非const演算子であるため、呼び出すoperator test_ref()ことはできません。const T&つまり、コピーであるべきだと思ったときに動きで人々を驚かせたくない限り、これを行うことはできません。

于 2011-05-16T22:23:55.410 に答える