2

私は非常に単純なAnyオブジェクトを書き込もうとしています。これは、任意のタイプのオブジェクトを保持できます。異種コンテナを実現するために、コンテナ内で使用したい。

#include <iostream>
#include <vector>
#include <string>

struct Any
{
    template < typename T >
    Any(const T & t) 
        :p(new storageImpl<T>(t)) { }

    ~Any() 
    {
        delete p;
    }

    struct storage
    {
        virtual ~storage() {}
    };

    template <typename T>
    struct storageImpl : storage
    {
        storageImpl(const T & t) : data(t) {}
        T data;
    };

    template <typename T>
    T & get()
    {
        storageImpl<T> * i = static_cast<storageImpl<T>*>(p);
        return i->data;
    }

    storage * p;
};

利用方法

int main ()
{
    //block1
    Any copy(Any(std::string("foo")));      
    std::cout << copy.get<std::string>();   

    //block2
    std::vector<Any> cont;
    cont.push_back(Any(5));
    cont.push_back(Any(37.9f));
    std::cout << cont[0].get<int>();    
    std::cout << cont[1].get<float>();  
}

コピーの作成に問題があります。

Anyベクター(// block2)にプッシュすると、名前のないAnyオブジェクトが破棄されるため、ポインターが削除され、プッシュされたオブジェクトは無効になります。

だから私は2つの質問があります:

1、クラスAnyのコピーコンストラクターを作成するにはどうすればよいですか?

2、block1の名前のないものAnyが破棄されないのに、そのポインタが削除されないのはなぜですか?\

私が試した編集

template <typename T>
Any(const Any & rhs)
    :p(new storageImpl<T>(rhs.get()))
{
}

ただし、トリガーされません。

4

2 に答える 2

2

Anyテンプレートクラスではありません。コピーコンストラクターをそのままテンプレート化しようとしてtemplate <typename T> Any(const Any & rhs)も意味がありません。

あなたができることは、仮想コンストラクターのイディオムを使用して、storageImplコピー自体を許可することです。これは、Boost.Any で使用されるメソッドでもあります。

struct Any {
    template < typename T >
    Any(const T& t) : p(new storageImpl<T>(t)) {}

    Any(const Any& other) : p(other.p->clone()) {}
 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    ~Any() { delete p; }

    struct storage {
        virtual ~storage() {}
        virtual storage* clone() = 0;
     // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    };

    template <typename T>
    struct storageImpl : storage {
        storageImpl(const T & t) : data(t) {}

        virtual storage* clone() { return new storageImpl(data); }
     // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        T data;
    };

    template <typename T>
    T& get() {
        storageImpl<T>* i = static_cast<storageImpl<T>*>(p);
        return i->data;
    }

    storage * p;
};

get()Any が本当に T を保持しているかどうかをメソッドがチェックしないなど、この実装には多くの問題があることに注意してください


ブロック 1 の無名の Any が破棄されないのはなぜですか? そのポインターは削除されません。

エリシオンをコピーします

于 2012-09-02T08:57:15.353 に答える
1
  1. ディープ コピーを作成します。つまり、コピーstorageImpl<T>元のオブジェクトのコンテンツに初期化された新しいオブジェクトを動的に割り当てます。

  2. コピー省略が発生する可能性があります。つまり、削除する一時オブジェクトがありません。

または、boost::anyを使用してすべての問題を回避します。

于 2012-09-02T08:46:58.453 に答える