析构函数用delete回收已分配的空间

xiaoshi935 2009-05-02 04:39:49
题目要求如下:
建立类与对象的程序
主要内容:
tnode的结构如下:
struct tnode
{
char *tword;
int count;
tnode *left,*right;
};
把tnode设计为带有构造函数和析构函数的类,要求构造函数使用new为tnode指向的串分配空间,析构函数用delete回收已分配的空间。
根据要求,本人写出了如下代码:

#include <iostream>
#include <string>
using namespace std;

class Tnode {
char *tword; //节点所存储的字符串
int count; //节点字符串长度
Tnode *left, *right; //指向前一个节点和后一个节点
public:
Tnode(char * pN ); //构造函数
~Tnode(); //析构函数
int length();
};

Tnode::Tnode(char * pN = "noName") {
cout << "构造对象 " << pN << endl;
tword = new char[strlen(pN)+1]; //字符串的长度要多加最后一个以0结尾的字节长度
if (tword) strcpy(tword, pN);
}

Tnode::~Tnode() {
cout << "析构对象 " << tword << endl;
delete [] tword;
}

Tnode::length() {
int l;
l = strlen(tword);
return l;
}

void main () {
Tnode t1("hello");
cout << "所构造对象的字符串长度为:" << t1.length() << endl;
}

运行也是可以通过,但是不知道left和right如何使用。下面写的这个是另外一个析构函数的版本,运行的时候错误百出:

Tnode::~Tnode() {
cout << "析构函数 " << tword << endl;
Tnode * temp;
Tnode * base;
base = tword;
while (base){
temp = base->right; //删除节点
delete base;
base = temp;
}
tword = base = temp = NULL;
}

之前也有发过一个类似帖子,但是还是不太懂有关如何类嵌套自己类的。希望高手给出有关如何解决的详细点的解释。
...全文
542 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoshi935 2009-05-02
  • 打赏
  • 举报
回复
回8楼:确实有问题。不过感觉我题目理解错了。7楼的回答应该是正解。
cyldf 2009-05-02
  • 打赏
  • 举报
回复

Tnode::~Tnode() {
cout << "析构函数 " << tword << endl;
Tnode * temp;
Tnode * base;
base = tword;//这里你的tword是char *,base 是Tnode *,会不会有问题?
while (base){
temp = base->right; //删除节点
delete base;
base = temp;
}
tword = base = temp = NULL;
}
windsting 2009-05-02
  • 打赏
  • 举报
回复
这里是类的具体实现:



//| File: linklist.cpp = a doubly linked list.
#include "linklist.h"
#define NULL 0L
CLinkedList::CLinkedList() // CLinkedList constructor
{
pHead = pTail = pCurPosition = NULL;
}
CLinkedList::~CLinkedList()// CLinkedList destructor - free each node
{
LPNODE pCur, pNext;
pCur = pHead;
pHead = pTail = pCurPosition = NULL;
// Go thru list and free each node
while (pCur != NULL)
{
pNext = pCur->pNext;
delete(pCur);
pCur = pNext;
}
}
// GetFirst - return app data for first entry in list and make it
// the current node.
void * CLinkedList::GetFirst()
{
pCurPosition = pHead;
if (pCurPosition == NULL)
{
return(NULL);
}
return(pCurPosition->pData);
}
// GetLast - return app data to last entry in list and make it
// the current node.
void * CLinkedList::GetLast()
{
pCurPosition = pTail;
if (pCurPosition == NULL)
{
return(NULL);
}
return(pCurPosition->pData);
}
// GetNext - return next app data entry in list and make it
// the current node.
void * CLinkedList::GetNext()
{
LPNODE pNext;
// check for empty list or already at end of list.
if ((pCurPosition == NULL) || (pCurPosition->pNext == NULL))
{
return(NULL);
}
pNext = pCurPosition->pNext;
pCurPosition = pNext;
return(pNext->pData);
}
// GetFirst - return app data that follows a given entry and make it
// the current node.
void * CLinkedList::GetNext(void *pData)
{
pCurPosition = Find(pData);
return(GetNext());
}
// GetPrev - return app data for previous entry in list and make it
// the current node.
void * CLinkedList::GetPrev()
{
LPNODE pPrev;
// check for empty list or already at start
if ((pCurPosition == NULL) || (pCurPosition->pPrev == NULL))
{
return(NULL);
}
pPrev = pCurPosition->pPrev;
pCurPosition = pPrev;
return(pPrev->pData);

}
// GetFirst - return app data that preceeds a given entry and make it
// the current node.
void * CLinkedList::GetPrev(void *pData)
{
pCurPosition = Find(pData);
return(GetPrev());
}
// Add - create a new node and put it at the start of the list and
// make it the current node.
void CLinkedList::Add(void *pData)
{
LPNODE pNew = new NODE;
// setup node and prepare it for its role as the new head of the list
pNew->pData = pData;
pNew->pNext = pHead;
pNew->pPrev = NULL;
// The old head of list (if any) should point to new node)
if (pHead != NULL)
pHead->pPrev = pNew;
// Make new node the head and current position
pHead = pNew;
pCurPosition = pNew;
// Check to see if new node is also the tail (ie. only list entry)
if (pTail == NULL)
pTail = pNew;
}
// Append - create a new node and put it at the end of the list.
void CLinkedList::Append(void *pData)
{
LPNODE pNew = new NODE;
// setup node and prepare it for its role as the new tail of the list
pNew->pData = pData;
pNew->pPrev = pTail;
pNew->pNext = NULL;
// The old tail of list (if any) should point to new node.
if (pTail != NULL)
pTail->pNext = pNew;
// Make new node the tail
pTail = pNew;
// Check to see if new node is also the head (ie. only list entry)
if (pHead == NULL)
{
pHead = pNew;
pCurPosition = pNew;
}
}
// Find - private method to find the node with the specified app data
// attached to it.
LPNODE CLinkedList::Find(void *pData)
{
LPNODE pCur;
// go thru list until we reach end or we find the right node.
for (pCur=pHead; (pCur != NULL) && (pCur->pData != pData); pCur= pCur->pNext);
return(pCur);
}
// Insert - create a new node and put it in front of the current
// position node and make it the current position.
void CLinkedList::Insert(void *pData)
{
LPNODE pNext, pPrev;
LPNODE pNew = new NODE;
pNew->pData = pData;
// check to be sure that there is a current node
if (pCurPosition != NULL)
{

// get pointers of current position
pPrev = pCurPosition->pPrev;
pNext = pCurPosition->pNext;
// set new nodes pointers for insertion into the list
pNew->pPrev = pPrev;
pNew->pNext = pCurPosition;
// Set the node in front of new node (if any) to point to it
if (pPrev != NULL)
{
pPrev->pNext = pNew;
// No node in front -> new node is at head
} else {
pHead = pNew;
}
// make new node the current node
pCurPosition = pNew;
// No current node, just Add to front
} else {
Add(pData);
}
}
// Insert - create a new node and put it in front of the specified
// node and make it the current position.
void CLinkedList::Insert(void *pData, void *pBefore)
{
// simply make the specified node current and insert the new
// node.
pCurPosition = Find(pBefore);
Insert(pData);
}

// Remove - remove a specified node from the list.
// Note: we do not delete the app data attached to the node!
void CLinkedList::Remove()
{
LPNODE pCur, pNext, pPrev;
pCur = pCurPosition;
if (pCur != NULL)
{
// save a copy of the links
pPrev = pCur->pPrev;
pNext = pCur->pNext;
// Is there a node ahead of us?
if (pPrev != NULL)
{
// yes -> update it to not point to us.
pPrev->pNext = pNext;
} else {
// no -> update head to not point to us.
pHead = pNext;
pCurPosition = pNext;
}
// Is there a node behind us?
if (pNext != NULL)
{
// yes -> update it to not point to us.
pNext->pPrev = pPrev;
pCurPosition = pNext;
} else {
// no -> update tail to not point to us.
pTail = pPrev;
pCurPosition = pPrev;
}
delete(pCur);
}
}
// Remove - remove a specified node from the list.
// Note: we do not delete the app data attached to the node!
void CLinkedList::Remove(void *pData)
{
pCurPosition = Find(pData);
Remove();
}
// RemoveFirst - remove the first node in the list and return the
// app data associated with it.
void * CLinkedList::RemoveFirst()
{
LPNODE pCur, pNext;
void *pData = NULL;
pCur = pHead;
// is there a node at the head?
if (pCur != NULL)
{
// take first node out of list.
pNext = pCur->pNext;
pHead = pNext;
pCurPosition = pNext;
// are there any nodes after us?
if (pNext != NULL)
{
// yes -> make it the new head
pNext->pPrev = NULL;
} else {
// no -> the list is now empty
pTail = NULL;
}
// get app data for node and then delete it
pData = pCur->pData;
delete(pCur);
}
return(pData);
}
// RemoveLast - remove the last node in the list and return the
// app data associated with it.
void * CLinkedList::RemoveLast()
{
LPNODE pCur, pPrev;
void *pData = NULL;
pCur = pTail;
// is there a node at the tail?
if (pCur != NULL)
{
// take last node out of list.
pPrev = pCur->pPrev;
pTail = pPrev;
// are there any nodes ahead of us?
if (pPrev != NULL)
{
// yes -> make it the new tail node
pPrev->pNext = NULL;
} else {
// no -> list is now empty
pHead = NULL;
pCurPosition = NULL;
}
// get app data for node and then delete it
pData = pCur->pData;
delete(pCur);
}
return(pData);
}

windsting 2009-05-02
  • 打赏
  • 举报
回复
你的问题其实就是关于双向链表的问题,给你一个双向链表的源代码,自己看看吧,
很多问题就可以迎刃而解了:


//| File: linklist.h
#ifndef _LINKLIST_H
#define _LINKLIST_H
typedef struct _NODE {
struct _NODE *pPrev;
struct _NODE *pNext;
void *pData;
} NODE, *LPNODE;
class CLinkedList {
private:
LPNODE Find(void *pData);
LPNODE pHead;
LPNODE pTail;
LPNODE pCurPosition;
public:
CLinkedList();
~CLinkedList();
void *GetFirst();
void *GetLast();
void *GetNext();
void *GetNext(void *pData);
void *GetPrev( );
void *GetPrev(void *pData);
void Add(void *pData);
void Insert(void *pData);
void Insert(void *pData, void *pBefore);
void Append(void *pData);
void Remove( );
void Remove(void *pData);
void *RemoveFirst();
void *RemoveLast();
};
#define LinkedList CLinkedList
#endif


认真看这个双向链表是如何处理其中的pPrev和pNext的,你的问题就解决了。
hjjdebug 2009-05-02
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lingyin55 的回复:]
如果你在调用new时使用了[],则你在调用delete时也使用[],如果你在调用new的时候没有[],那么你也不应该在调用时使用[]。
[/Quote]
问题是如果我new 时用了[], delete 时未使用[], 到底会发生什么事情呢?
反之也一样。
如果我new 时未用[], delete 时使用[],又发生了什么事情呢?
愿闻其详!
dongpf 2009-05-02
  • 打赏
  • 举报
回复
已经 delete base了,怎么到后面有对base操作?
是这里的问题吧。
cattycat 2009-05-02
  • 打赏
  • 举报
回复
delete [] tword;

没有[]吧。
另外感觉你这个有点像是字符串双向链表。有一个向链表增加字符串的函数才行。
jackyjkchen 2009-05-02
  • 打赏
  • 举报
回复
temp = base->right; //删除节点
delete base;
base = temp;
问题就在这里吧,base都被释放了,你还来base->right
lingyin55 2009-05-02
  • 打赏
  • 举报
回复
《Effective C++》中正确的观点、结论摘录如下:
1. 当你使用new时,有两件事会发生。第一,内存被配置(透过函数operator new)。第二,会有一个(或以上)的constructors针对此内存被调用。当你使用delete时,也有两件事发生:一个(或以上)的destructors会针对此内存被调用,然后内存被释放(透过函数operator delete)。
2. 如果你使用delete是未加括号,delete便假设删除对象是单一对象。否则便假设删除对象是个数组。
3. string *stringPtr1 = new string;
string *stringPtr2 = new string[100];
……
delete stringPtr1;
delete [] stringPtr2;
如果你对着stringPtr1使用“[]”形式,其结果未定义。如果你对着stringPtr2没有使用“[]”形式,其结果亦未定义。犹有进者,这对内建型别如int者亦未定义,即使这类型别并没有destructors。
4. 因此,很简单,如果你在调用new时使用了[],则你在调用delete时也使用[],如果你在调用new的时候没有[],那么你也不应该在调用时使用[]。

65,208

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧