C++ 析构函数在返回动态结构的函数中删除副本
好了,各位,没问题 所以我有一个模板类实现了一个单链表。我的程序中的类中的函数返回这些列表之一C++ 析构函数在返回动态结构的函数中删除副本,c++,constructor,destructor,C++,Constructor,Destructor,好了,各位,没问题 所以我有一个模板类实现了一个单链表。我的程序中的类中的函数返回这些列表之一 psList<int> psObj::getList() const { return List; } 下面是getList函数中的“返回列表”列表 head 0x616080 data 2 next 0x616060 data 12 next 0x0 同样的事情 下面是复制构造函数末尾的“原始”和“此”列表 “这个” “原件” 一切看起来都很好,不是吗 现在我们回到getList函
psList<int> psObj::getList() const {
return List;
}
下面是getList函数中的“返回列表”列表
head 0x616080
data 2
next 0x616060
data 12
next 0x0
同样的事情
下面是复制构造函数末尾的“原始”和“此”列表
“这个”
“原件”
一切看起来都很好,不是吗
现在我们回到getList函数,即将进入最后一个括号
psList<int> psObj::getList() const {
return List;
} // This bracket
现在我们进入最后一个括号,析构函数被称为
/*
* No idea what the in chrg thing is or why the debugger is telling me it was
* optimized out but I mentioned it here cause maybe it has something to do with my
* problem
*/
this 0x7ffffffe650
__in_chrg value optimized out
// Look familiar? well it should cause it is the head of the list I returned.
head 0x63c900
data 2
next 0x63a940
data 12
next 0x0
然后砰!我刚才复制并返回的列表被析构函数删除,因为它超出了范围
在绕道之后重申我原来的问题。如何在不让析构函数销毁所述副本的情况下,通过使用深度副本的函数返回动态结构
更多代码按要求提供
// Simple single link node with default constructor initializing the link to NULL.
template <class psClass>
struct psNode {
psClass data;
psNode<psClass>* next;
psNode() {
next = NULL;
}
};
//具有默认构造函数的简单单链接节点将链接初始化为NULL。
模板
结构psNode{
psClass数据;
psNode*next;
psNode(){
next=NULL;
}
};
以及推回功能
template<class psClass>
void psList<psClass>::pushback(psClass object) {
psNode<psClass>* ptr = new psNode<psClass>;
ptr->data = object;
if(head == NULL)
head = ptr;
else {
//Have to find the tail now
psNode<psClass>* tail;
psNode<psClass>* iterator = head;
while(iterator != NULL) {
tail = iterator;
iterator = iterator->next;
}
tail->next = ptr;
}
}
模板
void psList::pushback(psClass对象){
psNode*ptr=新的psNode;
ptr->data=对象;
if(head==NULL)
水头=ptr;
否则{
//我现在必须找到尾巴
psNode*尾;
psNode*迭代器=头;
while(迭代器!=NULL){
尾部=迭代器;
迭代器=迭代器->下一步;
}
tail->next=ptr;
}
}
是的,我知道跟踪尾巴会更容易
以下是psList类定义:
template <class psClass>
class psList {
public:
psList();
~psList();
psList(const psList &original);
psList(psNode<psClass>* _head);
void erase();
void pushfront(psClass object);
void pushback(psClass object);
bool isEmpty() const;
psNode<psClass>* front() const;
private:
psNode<psClass>* head;
};
模板
类列表{
公众:
psList();
~psList();
psList(常数psList和原件);
psList(psNode*_头);
无效擦除();
void pushfront(psClass对象);
void pushback(psClass对象);
bool isEmpty()常量;
psNode*front()常量;
私人:
psNode*头;
};
还没有重载的赋值运算符。我计划在跳过这一障碍后添加它。似乎
psList
的复制构造函数生成的是浅复制,而不是深复制。通常,如果管理类中的资源,则需要非平凡的复制构造函数、赋值运算符和析构函数(“三大”)。请向我们显示psList
的代码,您当前正在执行的操作如下:
psList<int> psObj::getList() const { return psList<int>(List); }
psList<int> newList; // psList default constructor called
newList = obj.getList(); // 1) obj.List copied via copy constructor within getList
// 2) copy of obj.List copy-assigned to newList (simple copy of head pointer)
// 3) copy of obj.List destructed
// newList now has head pointing to destroyed data
使用复制构造函数。通常情况下,两个副本会被压缩为一个副本
或者,如果要复制到现有对象,如中所示
psList<int> newList;
newList = obj.getList();
因此,在调用代码中发生的情况如下:
psList<int> psObj::getList() const { return psList<int>(List); }
psList<int> newList; // psList default constructor called
newList = obj.getList(); // 1) obj.List copied via copy constructor within getList
// 2) copy of obj.List copy-assigned to newList (simple copy of head pointer)
// 3) copy of obj.List destructed
// newList now has head pointing to destroyed data
psList newList;//psList默认构造函数调用
newList=obj.getList();//1) 通过getList中的复制构造函数复制的对象列表
//2)分配给新列表的对象列表副本(头指针的简单副本)
//3)已销毁对象列表的副本
//新列表现在的标题指向已销毁的数据
在您的情况下,这不是您想要的,您应该做的是确保拷贝分配真正形成了预期的深度拷贝(请参阅,以获取通过您已经实现的拷贝构造函数实现此操作的方法)
因此:如果您需要定义自己的析构函数、复制构造函数和复制赋值中任意一个的实现,那么您需要全部定义它们(或者至少将复制赋值和复制构造函数声明为private以使您的类不可复制)
另外,为什么不返回一个引用:
const psList<int> & psObj::getList() const { return List; }
constpslist&psObj::getList()const{return List;}
并让调用函数决定是否复制
psList<int> localList(localPsObj.getList());
psList localList(localPsObj.getList());
你应该熟悉一下。此外,除非这是家庭作业或学习练习,否则绝对不建议实现您自己的链表。您返回的链表肯定会被销毁,因为它已复制到return语句中,并且原始链表是您从中返回的函数的本地链表。您可能应该展示如何psList
,定义了psNode
和psList::pushback
。这是有道理的,但函数的本地部分和我返回的部分在内存中是相同的列表。如果它不是一个动态结构,那么我将声明someVar,返回someVar,它将创建自身的副本,然后函数中的someVar将被删除。但是现在我声明了一些列表,返回了一些列表,因为列表是内存中的地址,所以我也删除了列表。也许我在尝试做一些不可能的事情,但你肯定可以返回一个动态结构,而不会以某种方式破坏它。我将提供调试器的一些输出以更好地解释。我以为您在复制构造函数中进行“深度”复制?如果是这样的话,它们在内存中不是同一个列表,返回的值是函数的本地值的副本。不,深度复制和深度析构函数两者。您是如何得出这个结论的?构造函数的未知部分(pushback
)只接收psNode
的数据
部分,因此它很难重建指向原始psNode
的指针。不,复制构造函数肯定会进行深度复制。pushback创建指向空白新节点的指针,将数据复制到此节点中,然后将已生成列表中的最后一个节点链接到该节点(链接到null之前)。新节点中的链接已经指向null,因此没有任何操作。@Charles:好的,遗漏了只有数据传递到pushback
。请原谅我的无知,但是为什么我需要做psList psObj::getList()const{return psList(List);}据我所知,当函数需要返回值时,它会调用copy cons
psList<int> psObj::getList() const { return psList<int>(List); }
psList<int> newList = obj.getList(); // same as psList<int> newList(obj.getList());
psList<int> newList;
newList = obj.getList();
psList & psList::operator=(const psList& src) {
head = src.head;
}
psList<int> newList; // psList default constructor called
newList = obj.getList(); // 1) obj.List copied via copy constructor within getList
// 2) copy of obj.List copy-assigned to newList (simple copy of head pointer)
// 3) copy of obj.List destructed
// newList now has head pointing to destroyed data
const psList<int> & psObj::getList() const { return List; }
psList<int> localList(localPsObj.getList());