每次使用List的方法后调用C ++ List析构函数(C++ List destructor called after every use of List's method)

系统教程 行业动态 更新时间:2024-06-14 16:59:47
每次使用List的方法后调用C ++ List析构函数(C++ List destructor called after every use of List's method)

这是我之前提出的关于直接调用类的析构函数的问题的一个后续问题。

我正在为作业创建自己的列表。 我将任务,方括号,进出流操作员超载,并具有基本的添加,删除和打印功能。

我的下一步是让List删除并释放其所有节点的内存,这是我遇到的问题。

执行操作后,我将列表写入屏幕当前的状态,如下所示:

void main() { // Create instance of list List aList(true); List bList(true); aList.Add(1); aList.Add(2); bList.Add(2); cout << "aList: " << aList; cout << "bList: " << bList; aList = bList; cout << "aList: " << aList; cout << "bList: " << bList; aList.Add(3); cout << "aList: " << aList; cout << "bList: " << bList; int i = 0; cin >> i; }

这是我的超载流:

ostream &operator<<(ostream &stream, List theList) { stream << "There are " << theList._totalNodes << " nodes in the list." << endl; for(int i = 0; i < theList._totalNodes; i++) { stream << "Node #" << i << " holds the data: " << theList[i] << endl; } return stream; }

在使用此命令后,查看命令提示符窗口“Destructor called”也会打印在其下面。

列表析构函数:

List::~List() { cout << "Destructor called" << endl; // List::Destroy(); }

重载赋值运算符似乎也称为析构函数,这并不令我感到意外。 但是,其他人呢。

List &List::operator=(List &aList) { // Make sure not the same object trying to be copied if(this != &aList) { // Perform deep copy // Delete old pointers in redundant list, only if they exist already if(_head) { delete _head, _tail, _current, _del; _totalNodes = 0; // Reset total nodes } // Now set new pointers copied from other list _head = NULL; _tail = _head; _current = _head; _del = _head; // Now loop through all nodes in other list and copy them to this // Reset pointer in other list aList.Reset(); for(int i = 0; i < aList._totalNodes; i++) { Add(aList.Current()->_data); aList.Next(); } // Reset other list's pointer aList.Reset(); Reset(); // Reset our pointer } return *this; // Return for multi assignment }

我也有一个List的析构函数,在调用它时调用“Destructor called”,并注意到它在每次使用它的一个方法之后被调用。

为什么是这样? 我认为析构函数在对象不再需要时被调用,即被删除。

此外,当我遍历我的代码时,我注意到当一个指针被删除时,它指向的内存地址没有被取消。 删除后是否必须手动清空指针?

This is a follow up to a question I asked earlier today regarding the appropriation of directly calling a class' destructor.

I'm creating my own List for an assignment. I have overloaded the assignment, square brackets, in and out stream operators and have the basic adding, removing and printing to screen functionality.

My next step is to have the List delete and release the memory of all of its nodes, which I am having trouble with.

I have the List write to the screen its current state after performing its operations, as follows:

void main() { // Create instance of list List aList(true); List bList(true); aList.Add(1); aList.Add(2); bList.Add(2); cout << "aList: " << aList; cout << "bList: " << bList; aList = bList; cout << "aList: " << aList; cout << "bList: " << bList; aList.Add(3); cout << "aList: " << aList; cout << "bList: " << bList; int i = 0; cin >> i; }

Here is my overloaded out stream:

ostream &operator<<(ostream &stream, List theList) { stream << "There are " << theList._totalNodes << " nodes in the list." << endl; for(int i = 0; i < theList._totalNodes; i++) { stream << "Node #" << i << " holds the data: " << theList[i] << endl; } return stream; }

Looking at the command prompt window after this is used "Destructor called" is also printed underneath it.

The List destructor:

List::~List() { cout << "Destructor called" << endl; // List::Destroy(); }

The overloaded assignment operator also seems to call the destructor, which doesn't surprise me. However, the others do.

List &List::operator=(List &aList) { // Make sure not the same object trying to be copied if(this != &aList) { // Perform deep copy // Delete old pointers in redundant list, only if they exist already if(_head) { delete _head, _tail, _current, _del; _totalNodes = 0; // Reset total nodes } // Now set new pointers copied from other list _head = NULL; _tail = _head; _current = _head; _del = _head; // Now loop through all nodes in other list and copy them to this // Reset pointer in other list aList.Reset(); for(int i = 0; i < aList._totalNodes; i++) { Add(aList.Current()->_data); aList.Next(); } // Reset other list's pointer aList.Reset(); Reset(); // Reset our pointer } return *this; // Return for multi assignment }

I also have the destructor to a List write "Destructor called" when it's called and noticed that it is called after every use of one of its methods.

Why is this? I assumed the destructor is called when the object is no longer needed, i.e. deleted.

Furthermore, when stepping through my code I have noticed that when a pointer is deleted the memory address it is pointing to isn't being nullified. Do I have to manually NULL a pointer after it is deleted?

最满意答案

这是因为你按价值收取了你的列表 - 也就是你复制了它。 你需要通过const引用 - 也就是说,

ostream &operator<<(ostream &stream, const List& theList)

此外,您的赋值运算符应该采用const引用,而不是非const引用。

我也不认为这一点

delete _head, _tail, _current, _del;

做你认为它的作用。 它只是删除_del而没有其他的。

您应该使用递归自己拥有的设计,其中每个节点都会删除链中的下一个节点。 编辑:由于这不清楚,我会发布一个简短的示例。

template<typename T> struct Node { Node(const T& arg, Node* prev) : t(arg), previous(prev) {} T t; std::auto_ptr<Node<T>> next; Node<T>* previous; }; template<typename T> class List { std::auto_ptr<Node<T>> head; Node<T>* tail; public: List() : head(NULL), tail(NULL) {} void clear() { head = tail = NULL; } // Notice how simple this is void push_back() { push_back(T()); } void push_back(const T& t) { if (tail) { tail = (tail->next = new Node<T>(t, tail)).get(); return; } tail = (head = new Node<T>(t, NULL)).get(); } void pop_back() { tail = tail->previous; tail->next = NULL; } void pop_front() { head = head->next; } List<T>& operator=(const List& ref) { clear(); // Clear the existing list // Copy. Gonna leave this part to you. } };

注意我从来没有删除过任何东西 - std::auto_ptr为我做了所有事情,并且操纵列表并且它的节点变得更加容易,因为std::auto_ptr管理所有涉及的内存。 这个列表甚至不需要自定义析构函数。

我建议你std::auto_ptr阅读std::auto_ptr ,它在界面上有一些惊喜,比如“复制”构造函数和赋值操作符实际上是移动的,在使用这个类之前你会想知道它。 我希望我可以在所有的时候开始使用std::unique_ptr ,这会让生活变得更容易。

It's because you took your List by value- that is, you copied it. You need to take it by const reference- that is,

ostream &operator<<(ostream &stream, const List& theList)

Furthermore, your assignment operator should take a const reference, not a non-const ref.

I also don't think that this

delete _head, _tail, _current, _del;

does what you think it does. It just deletes _del and none of the others.

You should use a recursively self-owning design, where each node deletes the next one in the chain. Edit: As this was unclear, I'm going to post a brief sample.

template<typename T> struct Node { Node(const T& arg, Node* prev) : t(arg), previous(prev) {} T t; std::auto_ptr<Node<T>> next; Node<T>* previous; }; template<typename T> class List { std::auto_ptr<Node<T>> head; Node<T>* tail; public: List() : head(NULL), tail(NULL) {} void clear() { head = tail = NULL; } // Notice how simple this is void push_back() { push_back(T()); } void push_back(const T& t) { if (tail) { tail = (tail->next = new Node<T>(t, tail)).get(); return; } tail = (head = new Node<T>(t, NULL)).get(); } void pop_back() { tail = tail->previous; tail->next = NULL; } void pop_front() { head = head->next; } List<T>& operator=(const List& ref) { clear(); // Clear the existing list // Copy. Gonna leave this part to you. } };

Notice how I never deleted anything- std::auto_ptr did everything for me, and manipulating the list and it's nodes became much easier, because std::auto_ptr manages all of the memory involved. This list doesn't even need a custom destructor.

I suggest that you read up heavily on std::auto_ptr, it has some surprises in it's interface, like the "copy" constructor and assignment operator actually move, that you are going to want to know about before using the class. I wish I could start using std::unique_ptr instead all of the time, which would make life so much easier.

更多推荐

本文发布于:2023-04-17 09:04:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/dzcp/382f213b6049927bb84aecb7aef3c174.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   方法   List   method   called

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!