2016-04-30 47 views
0

損失不會忽略我有一個叫有向圖類,包含數組到節點指針:)列表類充滿指點回報

DiGraph::DiGraph(int Size) : count(0){ 
    nodes = new Node *[Size]; 
} 

現在我想要定義的功能getNodes(這基本上應該返回數組以列表形式:

Liste<Node*> DiGraph::getNodes() { 
    Liste<Node*> nlist(count+1); 
    for (int i = 0; i < count; i++) { 
     nlist.append(nodes[i]); 
    } 
    return nlist; 
} 

在NLIST正確填寫,但不知何故,在函數調用生成的副本不包含正確的指針,但所有其他變量的函數結束。

DiGraph a(6); 
a.addNode(new Node("A", 50, 50)); 
Liste<Node*> gN = a.getNodes(); //gN does not contain the same pointers that were returned 

'Liste'類基本上是一個帶有模板和一些奇特功能的動態數組。

現在我認爲答案可能是nlist在函數結束後被銷燬,但指針在節點變量中仍然有效,爲什麼副本包含無效的副本?

編輯

這是列表類:

#ifndef _LISTE_H 
#define _LISTE_H 

// ------------------------------------------------------------------- 
template <typename T> 
class Liste { 
private: 
    T *_values; 
    int _last; 
    int _size; 

    bool isFull(); 
    int find(T value); 
    void increase(); 
    void decrease(); 

public: 
    Liste(int size = 8); 
    Liste(Liste &list); 
    ~Liste(); 
    void append(T value); 
    void remove(T value); 
    T getValueAt(int pos); 
    int size(); 

    T operator[](int pos); 
}; 

// ------------------------------------------------------------------- 
template <typename T> 
Liste<T>::Liste(int size) { 
    _size = size; 
    _last = 0; 
    _values = new T[size]; 
} 

template <typename T> 
Liste<T>::Liste(Liste &list) { 
    _size = list._size; 
    _last = list._last; 
    _values = list._values; 
} 


// ------------------------------------------------------------------- 
template <typename T> 
Liste<T>::~Liste() { 
    delete[] _values; 
} 

// ------------------------------------------------------------------- 
template <typename T> 
void Liste<T>::increase() { 
    T *tmp = new T[_size * 2]; 

    for (int i = 0; i < _size; i++) 
     tmp[i] = _values[i]; 

    delete[] _values; 
    _values = tmp; 
    _size *= 2; 
} 

// ------------------------------------------------------------------- 
template <typename T> 
void Liste<T>::decrease() { 
    _size /= 2; 
    T *tmp = new T[_size]; 

    for (int i = 0; i < _size; i++) 
     tmp[i] = _values[i]; 

    delete[] _values; 
    _values = tmp; 
} 

// ------------------------------------------------------------------- 
template <typename T> 
bool Liste<T>::isFull() { 
    return _last == _size; 
} 

// ------------------------------------------------------------------- 
template <typename T> 
int Liste<T>::find(T val) { 
    int pos; 

    for (pos = 0; pos < _last; pos++) 
     if (_values[pos] == val) 
      return pos; 
    return -1; 
} 

// ------------------------------------------------------------------- 
template <typename T> 
T Liste<T>::getValueAt(int pos) { 
    if (pos < 0 || pos >= _last) 
     throw "OutOfBoundsException"; 

    return _values[pos]; 
} 

// ------------------------------------------------------------------- 
template <typename T> 
void Liste<T>::append(T val) { 
    if (isFull()) 
     increase(); 

    _values[_last] = val; 
    _last += 1; 
} 

// ------------------------------------------------------------------- 
template <typename T> 
void Liste<T>::remove(T val) { 
    int pos = find(val); 

    if (pos == -1) 
     throw "ValueNotFoundException"; 

    for (; pos < _last - 1; pos++) 
     _values[pos] = _values[pos + 1]; 
    _last -= 1; 

    if (_last < _size/4) 
     decrease(); 
} 

// ------------------------------------------------------------------- 
template <typename T> 
int Liste<T>::size() { 
    return _last; 
} 

// ------------------------------------------------------------------- 
template <typename T> 
T Liste<T>::operator[](int pos) { 
    return getValueAt(pos); 
} 

#endif 
+3

您正在返回一份'Liste '。你提供了一個合適的(深)複製構造函數嗎? –

+2

「一些奇特的功能」是否包含正確的拷貝構造函數? – user463035818

+0

' template Liste :: Liste(Liste&list){ \t _size = list._size; \t _last = list._last; \t _values = list._values; 「這樣就夠了嗎?因爲它沒有。 – Carl

回答

2
template <typename T> 
Liste<T>::Liste(Liste &list) { 
    _size = list._size; 
    _last = list._last; 
    _values = list._values; 
} 

這段代碼的作用是使新清單當然對象(從拷貝構造函數構造)指向的內存地址一個現有的Liste對象。但是這個對象將被銷燬,所以你得到一個懸掛指針。您需要執行值的硬拷貝。

template <typename T> 
Liste<T>::Liste(const Liste &list) { // <--- const 
    _size = list._size; 
    _last = list._last; 
    _values = new T[_size]; 
    for(std::size_t iter = 0 ; iter < _size ; ++iter) 
    { 
     _values[iter] = list._values[iter]; 
    } 
} 

這是良好的現代化實踐的指針成員換到一個智能指針(如​​)。通過這種方式,您將永遠不會忘記刪除所有內容,即使在構造函數不完整(引發異常)的情況下,也可以保證清除對象保留。

如果您計劃返回的值,你應該研究到如何讓你的清單當然類移動感知

T operator[](int pos);還可以通過引用返回一個包含項目,以允許對象的直接修改(T& operator[](int pos);)因爲它會返回位於_values[pos]的對象的副本,而且很可能不是您想要的。同樣適用於您的T getValueAt(int pos);公共方法。

+0

非常感謝您修復它,Liste課程由我的教授提供,但我理解您的最後一點是有道理的。我沒有使用智能指針或矢量,僅僅因爲講座還沒有覆蓋它。常量只是良好的習慣嗎?或者在這種情況下還有其他好處而不是安全嗎? – Carl

+0

@Siraja'const'在那裏,所以你不會錯誤地修改對象。它也可以讓你捕捉臨時對象(右值),你不能用簡單的引用來做。我猜測練習的重點是在複製構造函數中找到問題。 – GeorgeAl