出于学术目的,我正在尝试开发一些“文本冒险游戏”。我必须自己实现所有数据结构。现在,我在实现通用(模板)LinkedList方面遇到了一些问题。
具体来说,这个数据结构适用于所有(原始数据类型和自定义对象)但字符串! (标准库字符串)。
当我尝试将字符串添加到列表时,应用程序崩溃并出现以下错误(在控制台中):
“在抛出'std :: logic_error'的实例后终止调用 what():basic_string :: _ S_constructor null无效“
该列表使用头节点作为第一个节点
实现为“双链表”这里是代码(“Abstract”List接口):
#ifndef LIST_H_
#define LIST_H_
template <class T>
class List
{
public:
virtual ~List() {}
virtual T get(int position) = 0;
virtual List* add(T item) = 0;
virtual List* insert(T item, int position) = 0;
virtual List* remove(int position) = 0;
virtual int size() const = 0;
virtual bool isEmpty() const = 0;
protected:
private:
};
#endif /* LIST_H_ */
这是LinkedList实现(“节点”类):
#include "List.h"
#include <stdlib.h>
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_
template <class T>
class ListNode
{
public:
ListNode(T item)
{
mItem = item;
mNext = NULL;
mPrev = NULL;
}
ListNode(T item, ListNode<T>* next, ListNode<T>* prev)
{
mItem = item;
mNext = next;
mPrev = prev;
}
~ListNode()
{
delete &mItem;
}
T getItem()
{
return mItem;
}
ListNode<T>* getNext()
{
return mNext;
}
ListNode<T>* getPrev()
{
return mPrev;
}
void setItem(T item)
{
mItem = item;
}
void setNext(ListNode<T>* next)
{
mNext = next;
}
void setPrev(ListNode<T>* prev)
{
mPrev = prev;
}
protected:
private:
T mItem;
ListNode<T> *mNext, *mPrev;
};
LinkedList类:
template <class K>
class LinkedList : public List<K>
{
public:
LinkedList()
{
mSize = 0;
mFirstNode = NULL;
}
~LinkedList()
{
// implementazione distruttore tramite ciclo sui nodi
}
K get(int position)
{
K item = NULL;
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL) item = targetNode->getItem();
return item;
}
List<K>* add(K item)
{
if (mFirstNode == NULL)
{
mFirstNode = new ListNode<K>(item);
mFirstNode->setNext(mFirstNode);
mFirstNode->setPrev(mFirstNode);
}
else
{
ListNode<K>* newNode = new ListNode<K>(item, mFirstNode, mFirstNode->getPrev());
mFirstNode->getPrev()->setNext(newNode);
mFirstNode->setPrev(newNode);
}
mSize++;
return this;
}
List<K>* insert(K item, int position)
{
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL)
{
ListNode<K>* newNode = new ListNode<K>(targetNode->getItem(), targetNode->getNext(), targetNode);
targetNode->setItem(item);
targetNode->setNext(newNode);
mSize++;
}
return this;
}
List<K>* remove(int position)
{
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL)
{
targetNode->setItem(targetNode->getNext()->getItem());
targetNode->setNext(targetNode->getNext()->getNext());
//delete targetNode->getNext();
mSize--;
}
return this;
}
int size() const
{
return mSize;
}
bool isEmpty() const
{
return (mFirstNode == NULL) ? true : false;
}
protected:
ListNode<K>* getNodeAtPosition(int position)
{
ListNode<K>* current = NULL;
if (mFirstNode != NULL && position < mSize)
{
current = mFirstNode;
for (int i = 0; i < position; i++)
{
current = current->getNext();
}
}
return current;
}
private:
int mSize;
ListNode<K>* mFirstNode;
};
#endif /* LINKEDLIST_H_ */
建议?
答案 0 :(得分:5)
你的部分问题在于:
ListNode(T item)
{
mItem = item; // for a std::string, this will be a class member, non-pointer
mNext = NULL;
mPrev = NULL;
}
ListNode(T item, ListNode<T>* next, ListNode<T>* prev)
{
mItem = item; // same here
mNext = next;
mPrev = prev;
}
~ListNode()
{
delete &mItem; // you are attempting to delete an item you never created
}
您应该更改构造函数以在堆上创建T*
对象(然后将在析构函数中删除),或者从析构函数中删除delete
行。
顺便提一句,这个问题远远不仅仅是std::string
。
答案 1 :(得分:3)
你的程序中的某个地方你正在这样做:
std::string s(nullptr);
使用空指针调用std::string
的构造函数会导致它抛出std::logic_error
异常。
来自标准:
§21.4.2
basic_string(const charT * s,size_type n,const Allocator&amp; a = Allocator());
要求:s不应为空指针且n&lt;非营利组织。
答案 2 :(得分:0)
似乎无法将std :: string作为模板参数传递...
现在我使用“旧” - char const * - 来实现预期的结果,即使我必须实现我的个人“utils”方法来处理这些指针...