1

学習目的で非常に単純なSmartPointerを実装しようとしていますが、デバッグできないように見えるエラーに苦労しています。デバッグモードでも、何が間違っているのか明確な情報は得られず、ランタイムアサーションのみが得られます。

これまでのSmartPTRのコードは次のとおりです。

template <typename TYPE>
class SmartPointer
{
    TYPE* pData;
public:
    SmartPointer(void)
        : pData(0)
    {
        std::cout << "DEFAULT CTOR" << std::endl;
    }

    SmartPointer(TYPE* data)
        : pData(data)
    {
        std::cout << "CTOR WITH TYPE*" << std::endl;
    }

    SmartPointer(const SmartPointer<TYPE>& rhs)
    {
        std::cout << "COPY CTOR" << std::endl;
    }

    ~SmartPointer(void)
    { delete pData; }

    SmartPointer<TYPE>& operator=(const SmartPointer<TYPE>& rhs)
    {
        pData = rhs.pData;

        return *this;
    }

    TYPE* operator->(void)
    { return pData; }

    TYPE& operator*(void)
    { return *pData; }
};

私がこれで使用しているクラスは、かなり前向きです。これは、インターネット上のどこにでもある単純なPersonクラスであり、コンストラクター、コピーコンストラクター、およびオーバーロードされた代入演算子を備えています。単純なケースでは問題ありません。

SmartPointer<Person> p(new Person("Henry", 42));
p->Display(std::cout, *p); // Prints: Henry - 42
SmartPointer<Person> q(p); // Causes runtime error.
SmartPointer<Person> q;
q = p;                     // The same runtime error as with copy constructor.

これがどこでうまくいかなかったのか、何か考えはありますか?それが役立つ場合は、Personクラスがあります。

class Person
{
    std::string name;
    unsigned age;
public:
    Person(const char* name, unsigned age)
        : name(name), age(age)
    { std::cout << "PERSON CTOR CALLED!" << std::endl; }
    Person(const Person& rhs)
        : name(rhs.name), age(rhs.age)
    { std::cout << "PERSON COPY CTOR CALLED!" << std::endl; }
    ~Person(void)
    { }
public:
    Person& operator=(const Person& rhs)
    {
        std::cout << "PERSON ASSIGNMENT OPERATOR CALLED!" << std::endl;

        name = std::string(rhs.name);
        age  = rhs.age;

        return *this;
    }
public:
    static std::ostream& Display(std::ostream& os, const Person& p);
};

std::ostream& Person::Display(std::ostream& os, const Person& p)
{
    return os << p.name << " - " << p.age << std::endl;
}

すべての助けをありがとう!-ジョー。

4

1 に答える 1

2

スマートポインターは、コピーコンストラクターと代入演算子で基になるポインターをコピーするだけです。また、デストラクタのポインタも削除されます。したがって、これらのスマートポインターのいずれかをコピーまたは割り当てるたびに、それらがすべて削除しようとするものへのポインターを保持する複数のオブジェクトを取得します。

コピーコンストラクターに関して(これを指摘してくれた@andyprowlに感謝します)、スマートポインタークラスは初期化されていないポインターを保持し、それをdeleteデストラクタで呼び出そうとします。これは未定義の動作です。

この問題に対する一般的な解決策はありません。スマートポインターの動作方法と、スマートポインターが実装する所有権の種類を指定する必要があります。

于 2013-03-24T19:55:45.237 に答える