2017-02-25 11 views
0

私はテンプレートクラスを持って期待通りに動作していないチェックし、削除が

template <class T> 
class Node 
{ 
    private: 
     T data; 

    public: 
     Node<T> *next; 
     Node(T initial); 
     ~Node(); 
};  

とデストラクタです:

template <class T> 
Node<T>::~Node() 
{ 
    if (std::is_pointer<T>::value) 
    { 
     delete this->data; 
    } 
} 

template <class T> 
LinkedList<T>::~LinkedList() { 
    Node<T> *this_nodes = this->head; 
    Node<T> *next = NULL; 

    while (this_nodes) 
    { 
     next = this_nodes->next; 
     delete this_nodes; 
     this_nodes = next; 
    } 
} 

をしかし、私はとG ++でコンパイルしようとしたときにC++ 11

:、以下のドライバコード

LinkedList<int> list; 
list.insert(5); 
assert(list.read() == 5); 

で、私は次のエラーを取得します

error: type ‘int’ argument given to ‘delete’, expected pointer 

ノードはLinkedListの内部ですが、この質問に答えるのには完全には必要ではないので中止しました。私は、データを削除しようとする前にポインタであることを確認するためのチェックがあるので、なぜこのエラーが表示されるのか分かりません。

誰かがこれがうまくいかない理由/代替方法であることを私に少し詳しく教えてもらえますか? (注:この割り当てのためのスマートポインタを使用することはできません)

+1

'削除this->データを;' - 'データを'は' int'です。なぜそれを '削除 'しようとしていますか? enchroudingする 'Node 'は何を削除すべきか(そうでなければあなたのデストラクタは起動しないでしょう)。ポインターではないものを失格にしようとしている場合は、SFINAEや特殊化などのコード自体を省略する必要があります。実行時ifブロックではありません。 – WhozCraig

+2

なぜあなたは 'data'を最初から削除していますか?ほっといて。あなたのクラスは、データが動的に割り当てられているかどうかはわかりません。ポインタは 'new'で割り当てられる必要はないので、ポインタチェックは保証されません。 – PaulMcKenzie

+0

ドライバユーザーの他の部分は、int *、Card *(カスタムクラス)、その他いくつかの要素のような他の要素です。これらのデータは空のコンストラクタで削除されず、そのメモリを解放する方法がわかりません。私はデータがintであることを知っているので、if文は失敗し、何もしません。実際のポインタを型として取得したときにのみ反応する必要があります(ノードなど) – ZeldaZach

答えて

1

if文は、あなたのコード内でランタイムブランチを作成するためのツールです。条件付きコンパイルではありません。あなたはまだint型を削除する

Node<int>::~Node() 
{ 
    if (false) 
    { 
     delete this->data; 
    } 
} 

、それは枯れ枝の内側にいたとしても、コードは依然として有効である必要があります:あなたのテンプレートコードを拡張する場合、それは次のようになります。


解決策は実際にはポインタに触れないようにする必要があります。このコードが何を出力すると思いますか?

struct A { ~A() { std::cout << "~A()" << std::endl; } }; 

auto a = new A; 

std::vector<A*> vec; 

vec.emplace_back(a); 

vec.clear(); 

答えは何もありません。ベクタは自分のバッファを削除しますが、データは削除しません。あなたはそれが起こるしたい場合は、std::unique_ptrを使用します。

struct A { ~A() { std::cout << "~A()" << std::endl; } }; 

auto a = new A; 

std::vector<std::unique_ptr<A>> vec; 

vec.emplace_back(a); 

vec.clear(); 

今、誰もが出力~A()にこのコードを期待しています。あなたのコードも同じです。通常、型は自分自身を管理し、取得されたリソースを解放します。だからあなたのコードの変更は単に削除を削除し、それ自身を管理する型を取ることになります。


あなたが本当にとにかくそれをしたい場合は、私は本当にあなたがこれを行うことができ、はお勧めしません

template<typename T> 
void deleteIfPtr(T* ptr) { delete ptr; } 

template<typename T> 
void deleteIfPtr(const T&) { /* else, do nothing */ } 

template <class T> 
Node<T>::~Node() 
{ 
    deleteIfPtr(this->data); 
} 
+0

私はあなたの援助のために、unique_ptrに行くことにしました! – ZeldaZach

0

あなたはコンパイラに関係なくNodeをインスタンス化するために使用されるタイプのライン

 delete this->data; 

をコンパイルします

if (std::is_pointer<T>::value) 
    { 
     delete this->data; 
    } 

ロジックを使用することはできません。

別のものを使用する必要があります。例:

template <typename T> struct Deleter 
{ 
    static void deleteObject(T) { /* Do nothing */ } 
}; 

template <typename T> struct Deleter<T*> 
{ 
    static void deleteObject(T* obj) { delete obj; } 
}; 

template <class T> 
Node<T>::~Node() 
{ 
    Deleter<T>::deleteObject(data); 
} 
関連する問題