C++ 在链表开头插入时读取内存时出错

C++ 在链表开头插入时读取内存时出错,c++,memory-management,smart-pointers,singly-linked-list,C++,Memory Management,Smart Pointers,Singly Linked List,因此,我有一个链表类,它本身在功能上做得很好,但是当涉及到实际内存使用时(泄漏,到处泄漏),它是非常令人厌恶的 因此,我将在其中实现一个基本的智能指针类,以便更好地处理内存,但是在这个想法的实际实现部分,我遇到了一些粗略的问题 我只特别提到了我认为与该问题相关的内容,但是,如果有任何部分没有包括在内,可能证明是有用的,请询问,我可以发布整个内容 main.cpp: int main() { smartLinkedList<char*> moo2; moo2.inser

因此,我有一个链表类,它本身在功能上做得很好,但是当涉及到实际内存使用时(泄漏,到处泄漏),它是非常令人厌恶的

因此,我将在其中实现一个基本的智能指针类,以便更好地处理内存,但是在这个想法的实际实现部分,我遇到了一些粗略的问题

我只特别提到了我认为与该问题相关的内容,但是,如果有任何部分没有包括在内,可能证明是有用的,请询问,我可以发布整个内容

main.cpp:

int main()
{
    smartLinkedList<char*> moo2;
    moo2.insertAtFront("tail");
    moo2.insertAtFront("one");
    moo2.insertAtFront("head");
    for(int j = 0; j < moo2.length() ; j++)
        cout << moo2.goToFromFront(j) << endl;

    cin.ignore(1);
    return 0;
}
intmain()
{
smartLinkedList moo2;
2.插入式前部(“尾部”);
2.插入式前部(“一”);
2.插入式前部(“头部”);
对于(int j=0;j下一步;
如果(临时->下一步==NULL)
返回温度->数据;
}
返回温度->数据;
}
};
smartPointer.h:

#pragma once

class referenceCount
{
private:
    int count;
public:
    void add()
    {
        count++;
    }
    int release()
    {
        return --count;
    }
};

//for non-learning purposes, boost has a good smart pointer
template <class type>
class sPtr
{
private:
    type *p;
    referenceCount *r;
public:
    sPtr()
    {
        p = NULL;
        r = new referenceCount();
        r->add();
    }
    sPtr(type *pValue)
    {
        p = pValue;
        r = new referenceCount();
        r->add();
    }
    sPtr(const sPtr<type> & sp)
    {
        p = sp.p;
        r = sp.r;
        r->add();
    }
    ~sPtr()
    {
        if(r->release() == 0)
        {
            delete p;
            delete r;
        }
    }

    type* get()
    {
        return p;
    }

    type& operator*()
    {
        return *p;
    }
    type* operator->()
    {
        return p;
    }
    sPtr<type>& operator=(const sPtr<type>& sp)
    {
        if (this != &sp) //self assignment
        {
            /*if(r->release() == 0)
            {
                delete p;
                delete r;
            }*/ //this will cause an error when you take something with no references and set it equal to something

            p = sp.p;
            r = sp.r;
            r->add();
        }
        return *this;
    }
};
#pragma一次
类引用计数
{
私人:
整数计数;
公众:
void add()
{
计数++;
}
int release()
{
返回——计数;
}
};
//对于非学习目的,boost有一个很好的智能指针
模板
sPtr类
{
私人:
*p型;
参考计数*r;
公众:
sPtr()
{
p=零;
r=新的引用计数();
r->add();
}
sPtr(类型*pValue)
{
p=pValue;
r=新的引用计数();
r->add();
}
sPtr(施工sPtr和sp)
{
p=sp.p;
r=sp.r;
r->add();
}
~sPtr()
{
如果(r->release()==0)
{
删除p;
删除r;
}
}
键入*get()
{
返回p;
}
类型和运算符*()
{
返回*p;
}
类型*运算符->()
{
返回p;
}
sPtr和操作员=(常数sPtr和sp)
{
if(this!=&sp)//自分配
{
/*如果(r->release()==0)
{
删除p;
删除r;
}*///当您获取没有引用的内容并将其设置为相等时,这将导致错误
p=sp.p;
r=sp.r;
r->add();
}
归还*这个;
}
};
节点h:

#pragma once

template <class type>
struct node
{
    type data;
    node *next;

    node() 
    {
        next = NULL;
    }
};
#pragma一次
模板
结构节点
{
类型数据;
节点*下一步;
节点()
{
next=NULL;
}
};
从链表的goToFromFront(int)中的if语句中专门抛出“无法从0xfdfe01读取”的行,其中,在主循环中的点j=2处抛出错误。查看MSVS2010调试器时,temp->next是未知的(CXX0030:error,表达式无法计算),在我看来它应该转换为null,但表达式首先抛出了一个无法读取的错误


老实说,我不确定我做错了什么,因为这对我来说都是一个学习过程,任何批评都是高度赞赏的。提前谢谢

这些应该可以解决您的问题:

取消对sPtr运算符=中的代码的注释或使用交换习惯用法:

sPtr<type>& operator=(const sPtr<type>& rhs)
{
    if (this != &rhs) // self assignment
    {
        sPtr<type> tmp(rhs);
        std::swap(this->p, tmp.p);
        std::swap(this->r, tmp.r);
    }
    return *this;
}

template <class T>
class node
{
public:
    T data;
    sPtr<node<T> > next;
};

bool insertAtFront(type obj)
{
    sPtr<node<type>> temp(new node<type>);
    temp->data = obj;
    temp->next = head;
    head = temp;
    size++;
    return true;
}

通过使用侵入式引用计数而不是单独的引用计数,您可能会使事情变得更简单;更重要的是,您应该为
操作符=
实现使用复制和交换习惯用法。@Medinoc我在发布这篇文章之前,实际上很想继续重写引用计数,但我想我不想在无法完全测试的情况下意外添加另一个bug。感谢您提供的复制和交换参考,我以前没有听说过,我将很快实现它。您不会丢失太多代码,这些代码将使此完全编译。为节点添加引用和其他缺失的内容,如果我们能够自己完全构建它,我们就更有可能提供帮助。@MikeVine我添加了节点和我最近的一些更改。它应该可以在你这边编译,省去我来这里的明显错误。恐怕我不明白。除了第五行使用head.get()之外,您发布的代码与我的代码完全相同,它必须用作head本身是一个智能指针,接下来是一个节点*。不管这种细微差别如何,都会注释掉将在=运算符上递减的部分。除非在较低的级别上发生其他事情,否则我不确定refCount会在何处或如何减少。你能进一步解释一下你的意思吗?(也就是说,我认为你是对的,我确实认为它指向垃圾,我只是不理解如何/为什么)我在你的代码中取消了assign中的部分注释(应该按照建议使用swap进行显示或重写),以产生问题(在c++11中使用gcc)。然后我修复了“Insertafront”。使用head.get()的区别在于对构造函数(type*)的隐式调用,该构造函数创建了一个临时对象(您可以通过在“sPtr(type*pValue)”之前添加关键字“explicit”来禁止该隐式调用)。那个临时的有它自己的refcount,并且被销毁了。我想我开始更好地理解你的意思了,我想我理解错误发生的地方,但我不知道如何修复它。尝试执行temp->next=head会导致类型不匹配,我只能执行type->next=&*head或type->next=head.get(),我不知道如何实现显式,而几乎所有操作都会出错。你能给我看一些代码剪贴画什么的吗?答案更新了,现在我们有了你的“节点”版本。我用的是我的版本,所以我之前的评论并不完全适用于你的案例。这做得很完美,解决了一个我苦苦挣扎了几个小时的问题。谢谢你并没有表现出足够的感激。
sPtr<type>& operator=(const sPtr<type>& rhs)
{
    if (this != &rhs) // self assignment
    {
        sPtr<type> tmp(rhs);
        std::swap(this->p, tmp.p);
        std::swap(this->r, tmp.r);
    }
    return *this;
}

template <class T>
class node
{
public:
    T data;
    sPtr<node<T> > next;
};

bool insertAtFront(type obj)
{
    sPtr<node<type>> temp(new node<type>);
    temp->data = obj;
    temp->next = head;
    head = temp;
    size++;
    return true;
}
explicit sPtr(type *pValue)