当我实现保存节点的堆栈的pop()和析构函数时,我应该在删除节点本身之前删除node->数据,还是应该删除节点并让创建node->数据的调用者删除node->数据?如果让调用者这样做,调用者何时以及如何删除数据?它应该以这种方式调用:{data = stack.top();删除数据; stack.pop();}?
我还没有看到任何删除node->数据的代码,无论是pop()的实现还是调用函数。这就是为什么我感到困惑。
这里我复制了我使用链接列表实现的堆栈。请查看pop()和~stack()的注释以解决我的问题。谢谢你的帮助。
typedef struct Node_t{
struct Node_t* next;
void* data;
}Node;
class stack {
public:
stack(): _head(null), _size(0){}
~stack();
void push(void* data);
void pop();
void* top();
bool empty();
stack(const stack& original);
stack& operator=(const stack& original);
private:
Node* _head;
int _size;
};
stack::~stack{
Node* next = null;
while(_head){
next = _head->next;
//should delete _head->_data???
delete _head;
_head = next;
}
_size = 0;
}
void stack::push(void* data){
Node* elem = new Node;
elem->data = data;
elem->next = _head;
_head = elem;
_size++;
}
void stack::pop(){
Node* next = NULL;
if (_head) {
next = _head->next;
//should delete _head->_data???
delete _head;
_head = next;
_size--;
}
}
void* stack::top() const{
if (_head) {
return _head->_data;
}
}
bool stack::empty(){
if(_size>0) return false;
else return true;
}
答案 0 :(得分:2)
您的数据是指向其他地方的指针。这里的策略是:在堆栈外部创建数据对象,并将数据指针推入堆栈。因此,通过对称性,删除数据的控制也应该存在于堆栈的外面。如果您不需要,则需要明确删除它。例如:
stack s;
char mydata[] = {'a','b','c'};
s.push((void*)mydata);
//do things
s.pop();
delete [] mydata;
如果你真的想控制堆栈中的数据(通过它可能不是一个好主意,假设你的数据可能在其他地方使用),那么也存在问题。因为数据类型无效*您可能无法“安全地”删除它。请参阅此主题Is it safe to delete a void pointer?
答案 1 :(得分:1)
这个答案有几个部分:
对于实际编程,没有理由建立自己的数据结构,而标准库已经提供了这些数据结构。
如果你必须建立自己的数据结构作为学习练习,原则上你可以拥有你想要的任何分配和删除语义。
但是,如果你必须构建自己的堆栈,我强烈建议遵循与标准库stack相同的语义,它使用复制和引用语义来避免显式分配和删除用户代码。
遵循标准库语义可提高一致性,减少理解界面时的认知负担,并大大降低内存泄漏的可能性。