2016-04-30 38 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