C++ 使用智能指针的链表-哪里出了问题? #包括 #包括 #包括 使用名称空间std; 类异常 { 受保护的: 字符串描述; 公众: spexception(); spexception(常量字符串&); 虚拟常量字符串&what(); }; 模板 类sp { 私人: T*p; sp(T*); 公众: sp(); 警司(const T),; sp(int); T&算子*(); T*运算符->(); sp&运算符=(const sp&); sp&运算符=(常数T&); sp&运算符=(int); 布尔运算符==(常量sp&); ~sp(); }; spexception::spexception():说明(“无说明”) {} spexception::spexception(常量字符串&s):描述 {} 常量字符串和spexception::what() { 返回说明; } 模板 sp::sp() { p=零; } 模板 sp::~sp() { 如果(p!=NULL)删除p; } 模板 sp::sp(常数T&T) { p=新的T(T); } 模板 sp::sp(int i) { 如果(i!=0)抛出spexception(“智能指针不能从非零整数初始化”); p=零; } 模板 sp&sp::运算符=(常量sp&q) { 如果(*this==q)返回*this; 如果(p!=NULL)删除p; p=q.p; 归还*这个; } 模板 sp&sp::运算符=(常量T&T) { p=新的T(T); } 模板 sp&sp::operator=(int i) { 如果(i!=0)抛出spexception(); p=零; } 模板 布尔sp::运算符==(常量sp&q) { 回报率(p==q.p); } 模板 T&sp::运算符*() { 返回*p; } 模板 T*sp::运算符->() { 返回p; } 使用名称空间std; 类节点 { 公众: int-val; sp next; 节点() { val=5; } 节点(int v):val(v) { cout模板 sp&sp::运算符=(常量sp&q) { 如果(*this==q)返回*this; 如果(p!=NULL)删除p; p=q.p; 归还*这个; }

C++ 使用智能指针的链表-哪里出了问题? #包括 #包括 #包括 使用名称空间std; 类异常 { 受保护的: 字符串描述; 公众: spexception(); spexception(常量字符串&); 虚拟常量字符串&what(); }; 模板 类sp { 私人: T*p; sp(T*); 公众: sp(); 警司(const T),; sp(int); T&算子*(); T*运算符->(); sp&运算符=(const sp&); sp&运算符=(常数T&); sp&运算符=(int); 布尔运算符==(常量sp&); ~sp(); }; spexception::spexception():说明(“无说明”) {} spexception::spexception(常量字符串&s):描述 {} 常量字符串和spexception::what() { 返回说明; } 模板 sp::sp() { p=零; } 模板 sp::~sp() { 如果(p!=NULL)删除p; } 模板 sp::sp(常数T&T) { p=新的T(T); } 模板 sp::sp(int i) { 如果(i!=0)抛出spexception(“智能指针不能从非零整数初始化”); p=零; } 模板 sp&sp::运算符=(常量sp&q) { 如果(*this==q)返回*this; 如果(p!=NULL)删除p; p=q.p; 归还*这个; } 模板 sp&sp::运算符=(常量T&T) { p=新的T(T); } 模板 sp&sp::operator=(int i) { 如果(i!=0)抛出spexception(); p=零; } 模板 布尔sp::运算符==(常量sp&q) { 回报率(p==q.p); } 模板 T&sp::运算符*() { 返回*p; } 模板 T*sp::运算符->() { 返回p; } 使用名称空间std; 类节点 { 公众: int-val; sp next; 节点() { val=5; } 节点(int v):val(v) { cout模板 sp&sp::运算符=(常量sp&q) { 如果(*this==q)返回*this; 如果(p!=NULL)删除p; p=q.p; 归还*这个; },c++,C++,在上述函数中,指针“p”被删除,下一条指令尝试将值“q.p”分配给删除的“p”,这可能会导致问题 我对上述函数做了如下更改 template<class T> sp<T>& sp<T>::operator = (const sp& q) { if(*this==q) return *this; if(p!=NULL) delete p; p

在上述函数中,指针“p”被删除,下一条指令尝试将值“q.p”分配给删除的“p”,这可能会导致问题

我对上述函数做了如下更改

template<class T>

        sp<T>& sp<T>::operator = (const sp& q)
        {
            if(*this==q) return *this;
            if(p!=NULL) delete p;
            p = q.p;
            return *this;
        } 
模板
sp&sp::运算符=(常量sp&q)
{
如果(*this==q)返回*this;
如果(p!=NULL)p=q.p;
归还*这个;
}

这很好。

您没有复制构造函数,因此默认的复制构造函数将只复制指针,给您两个指向同一对象的智能指针对象

类似地,赋值运算符只复制指针,为您提供指向同一对象的两个智能指针对象

无论何时发生上述任何一种情况,第一个智能指针的析构函数都会删除该对象,而另一个智能指针处于悬空状态。当第二个智能指针被销毁时,它会再次删除已删除的指针,从而导致未定义的行为


复制或分配智能指针时,还需要克隆指向的对象,或者在某个位置有一个引用计数,用于跟踪指向同一对象的指针的数量。在后一种情况下,只有当引用计数降至0时,才能删除该对象。

作为旁注:
如果(p!=NULL)delete p;
相当于
delete p;
看起来像是一个典型的所有权问题。您有两个指针指向列表中的最后一个节点;
last
,以及其上一个节点的
next
节点。当
next
节点被销毁时,节点被解除分配,因此
last
的销毁是未定义的。Linked列表并不是智能指针的好应用程序,您的
sp
类的赋值操作符复制指针。由于
sp
删除了所拥有的指针,这会导致从中分配的所有指针被删除两次。问题是为什么节点析构函数执行无限次?我建议避免
t安装
s,直到您调试它。
模板
s因给出异常错误消息而臭名昭著,即使是最简单的错误也是如此。如果p已经指向堆上的某个位置,并且在没有首先删除它的情况下重新分配了它,那么这可能会导致内存泄漏。我已经用valgrind测试了代码的内存泄漏,但没有显示出来任何,在某些情况下可能。
template<class T>

        sp<T>& sp<T>::operator = (const sp& q)
        {
            if(*this==q) return *this;
            if(p!=NULL) delete p;
            p = q.p;
            return *this;
        } 
template<class T>
sp<T>& sp<T>::operator = (const sp& q)
{
    if(*this==q) return *this;
    if(p!=NULL) p = q.p;
    return *this;
}