C ++自定义模板LinkedList崩溃添加std :: string

时间:2013-08-20 19:31:08

标签: c++ string list nodes

出于学术目的,我正在尝试开发一些“文本冒险游戏”。我必须自己实现所有数据结构。现在,我在实现通用(模板)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_ */

建议?

3 个答案:

答案 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作为模板参数传递...

Strings as Template Arguments

现在我使用“旧” - char const * - 来实现预期的结果,即使我必须实现我的个人“utils”方法来处理这些指针...