2011-04-22 174 views
0
template <class T> 
class ListNode { 

public: 
    T* data; 
     ListNode<T>* next; 
} 

可以說我有一個列表節點模板,並在代碼中的某處我想獲取數據的副本 - 意味着不是指向數據(T *)的指針的副本,而是一個新的指針(T *),它將指向存儲器中具有相同信息的另一個地方。C++模板問題

如何在使用C++模板時執行此操作?我怎樣才能複製(*數據),如果我不知道什麼是

+3

當你知道類型時,你如何做到這一點?它適用於模板類型。 – 2011-04-22 14:12:38

+1

您*知道類型...'T' – 2011-04-22 14:13:42

+0

@Konrad:或者,它同樣不適用於非模板。到目前爲止所有的答案都會導致切片。 – 2011-04-22 14:28:32

回答

0

T有要被複制施工的,這樣就可以做

template <class T> 
    ListNode<T>::ListNode(const ListNode<T>& src) 
    { 

     ... 
     // given a preexisting copy, src, create a new T to 
     // perform a copy 
     T* destT = new T(*srcT); 
    } 

T的類型。如果T有一個拷貝構造函數,這將起作用。如果沒有,編譯器會給你一個錯誤(可能是一個非常神祕的錯誤)

+0

NM ...它涉及咖啡,它不是你的最終目的。 – 2011-04-22 14:21:27

+0

爲什麼編譯器應該給出錯誤; 編譯器不會生成默認的拷貝構造函數嗎? – iammilind 2011-04-22 14:29:11

0

使用運算符=或複製構造函數。這是標準做法,它們都會生成對象的副本。

因此,舉例來說:

T *p = other_pointer; 
*p = *data; 

或者

T* copy = new T(*data); 
+1

適用於允許切片的「生成副本」的值。 – 2011-04-22 14:31:25

+0

@本:沒有標準的虛擬複製功能,所以你拿你可以得到的。 – 2011-04-22 17:24:10

0

當創建一個模板類型的副本,實際上你不用擔心的類型,例如,住該任務上的副本構造函數或該類型的賦值運算符:

template <class T> 
class ListNode { 
public: 
    T* data; 
    ListNode<T>* next; 
    T* getCopy() { new T(*data); } // get copy of "data" 
}; 

假設您使用此ListNode<T>class A,那麼你可以有在定義(和賦值運算符以及)拷貝構造函數:

class A { 
public: 
    A(const A& copy); 
}; 

現在,當ListNode<T>::getCopy()被調用時,它會調用的內部拷貝構造函數。

+0

-1:每次有人要求複製時,潛在的內存泄漏可能不是一個好設計......將其包裝在智能指針中,或者最好提供顯式拷貝構造函數和/或賦值運算符。 – AJG85 2011-04-22 15:02:42

+0

@ AJG85,我不這麼認爲是內存泄漏。提問者詢問'T *'的副本,它可以存儲在其他對象的'data'成員中,並且可以在析構函數中被刪除。 – iammilind 2011-04-23 04:40:33

+0

您返回一個像這樣的副本:'T getCopy()const {* data; }'你正在做的是在堆上分配內存並在一個** public **方法中返回一個指向它的指針,這很容易導致內存泄漏和孤兒指針......調用你的方法的任何人都必須存儲指針並調用delete '以避免內存泄漏,沒有例外。 – AJG85 2011-04-25 15:47:27

1

編譯器知道T的類型。不知道的是指向多少個實例T。在獲得實際的實現方面,簡短的答案是不要使用指針類型。改用容器。由於無論如何您都在複製節點數據,所以開銷很小。下面明顯的例子:

template <class T> 
class ListNode { 
public: 
    // use a vector as the container 
    std::vector<T> data; 
    ListNode<T>* next; 
    // initializer from pointer primitive 
    ListNode(const T* ps,size_t elements) 
    { 
     data.assign(ps,ps+elements); 
    } 
    // copy templated instance 
    ListNode(const ListNode& arg) 
    { 
     data = arg.data; 
    } 
    // assignment 
    ListNode& operator=(const ListNode& arg) 
    { 
     if (this != &arg) 
     { 
      data = arg.data; 
     } 
     return *this; 
    } 
}; 

實際使用量將與此類似:

{ 
    const char* ps = "Hello World"; 
    ListNode<char> ln1(ps,strlen(ps)); 
    ListNode<char> ln2 = ln1; 
} 

你可以,當然,變得更加複雜,解決方案,但他們都將涉及保留的實例數的軌道鍵入指針指向的T

+0

+1:儘管範例的範圍仍然是一個簡單的選擇,簡單是好的。 – AJG85 2011-04-22 15:16:09