c++ - 充满指针的列表类在返回时丢失地址

标签 c++ pointers

我有一个名为 DiGraph 的类,它包含一个指向节点指针的数组:

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

最佳答案

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

这段代码所做的是使新的 Liste 对象(从复制构造函数构造)指向现有 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];
    }
}

将指针成员包装到智能指针(例如 unique_ptr<> )是一种很好的现代做法。这样您就永远不会忘记删除所有内容,即使在构造函数不完整(抛出异常)的情况下,也可以保证清除对象保留。

如果你打算按值返回,你应该研究如何让你的 Liste 类移动感知

你的 T operator[](int pos);还可以通过引用返回包含的项目,以允许立即修改对象 ( T& operator[](int pos); ) 因为实际上,它返回位于 _values[pos] 的对象的拷贝。并且很可能不是您想要的。同样对于您的 T getValueAt(int pos);公共(public)方法。

关于c++ - 充满指针的列表类在返回时丢失地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36959263/

相关文章:

pointers - 为什么在本 golang 教程中将指针用于结构实例?

c - 想要从C中的结构体内存中访问结构体指针类型的数据

qt - 如何在QT中访问父控件指针

c - 从内存地址中减去?

在 C 中复制不确定的指针

c++ - 如何检测DTLS中收到的消息?

c++ - 递归调用可变参数模板函数重载时调用不明确

c++ - 使用堆栈和迭代器编写后缀计算器

c++ - 如何用蛮力解决 8 皇后一维数组?

c++ - Xcode C++,无法从 main 调用指针返回方法