C++ 在链表深度复制构造函数中,指针永远不会达到null
我目前正在构建一个名为Sequence的链表类。有四个私有节点-headPtr、tailPtr、cursor(当前节点)和preducer(前一个节点)C++ 在链表深度复制构造函数中,指针永远不会达到null,c++,pointers,linked-list,copy-constructor,C++,Pointers,Linked List,Copy Constructor,我目前正在构建一个名为Sequence的链表类。有四个私有节点-headPtr、tailPtr、cursor(当前节点)和preducer(前一个节点) 我的复制构造函数在光标是列表中的最后一个项目时工作得很好,但是当光标处于中间时,由于函数的原因,函数从不退出while循环。p> 以下是复制构造函数: Sequence::Sequence(常量序列和copyMe){ 拷贝(copyMe); } 无效序列::复制(常量序列和copyMe){ numitems=0; if(copyMe.headP
我的复制构造函数在光标是列表中的最后一个项目时工作得很好,但是当光标处于中间时,由于函数的原因,函数从不退出while循环。p> 以下是复制构造函数:
Sequence::Sequence(常量序列和copyMe){
拷贝(copyMe);
}
无效序列::复制(常量序列和copyMe){
numitems=0;
if(copyMe.headPtr==nullptr){
光标=前驱体=头部PTR=尾部PTR=空PTR;
}
否则{
//为新序列分配一个新节点
node*newPtr=新节点;
newPtr->data=copyMe.headPtr->data;
numitems++;
//使用此节点启动新序列
headPtr=新PTR;
前体=nullptr;
游标=头PTR;
tailPtr=headPtr;
//创建节点以遍历原点序列
节点*originPtr=copyMe.headPtr->next;
while(originPtr!=nullptr){
//将节点添加到新列表中,使其成为当前节点,并分配数据(&S)
newPtr->next=新节点;
newPtr=newPtr->next;
newPtr->data=originPtr->data;
numitems++;
//正确的光标和光标位置
if(originPtr==copyMe.cursor){
此->光标=newPtr;
}
else if(originPtr==copyMe.preducer){
此->前体=新PTR;
}
originPtr=originPtr->next;
//如果被复制的东西是最后一件东西,请将其设置为tailptr
if(originPtr==nullptr){
tailPtr=newPtr->next;
cout复制构造函数的正确语法是:
Sequence::Sequence(const Sequence& copyMe) {...}
你写了:
void Sequence::copy(const Sequence& copyMe) {...}
这意味着您定义了一个成员函数而不是构造函数。因此永远不会调用您的构造函数。当您创建copy1、copy2和copy3时,将使用默认构造函数
更新
if (originPtr == nullptr) {
tailPtr = newPtr->next; // newPtr->next is not initialized here
// consider tailPtr = newPtr instead
cout << "tail assigned" << endl;
newPtr->next = nullptr; // good
originPtr = nullptr; // originPtr is nullptr here because of if condition
}
更新3
Sequence copy2(original);
original.remove_current(); // here you remove the last element
问题似乎出在remove\u current()中
。构造函数中的循环不取决于光标位置。但它取决于原始序列的节点->下一个值。因此,创建副本时出错不会导致无限循环。无限循环的唯一原因是原始序列的格式不正确。我怀疑您忘了更新上一个no的下一个值在从序列中删除最后一个元素后执行de。在您发布remove_current()的代码之前,我无法证明我的话
更新4
void Sequence::remove_current() {
if (is_item()) {
node* temp;
temp = cursor;
if (cursor == headPtr && cursor == tailPtr) {
cursor = nullptr;
precursor = nullptr;
headPtr = nullptr;
tailPtr = nullptr;
}
else if (cursor == headPtr) {
headPtr = cursor->next;
cursor = headPtr;
precursor = nullptr;
}
else {
if (cursor == tailPtr) {
precursor->next = nullptr;
tailPtr = precursor;
cursor = precursor;
if (precursor == headPtr) {
precursor = nullptr;
}
else {
for(precursor = headPtr; precursor->next->next; precursor = precursor->next);
}
}
else {
precursor->next = cursor->next;
cursor = cursor->next;
}
}
delete temp;
numitems--;
}
}
1) 您是否尝试过使用调试器逐行检查代码,同时在每个执行步骤中观察每个变量的值,以查看它们是否符合您的期望值?2)请提供。减少TESTSIZE变量并在visual studio中逐步检查您的程序。这总能帮助我找到错误所在。我不确定问题是复制构造函数(对我来说似乎很好,正如您所说,我认为光标的位置不应该有任何区别)。但是自从上次调用复制构造函数以来,您对原始的
进行了相当多的修改,所以这可能就是问题所在。@n314159我省略了在尾部测试游标复制后测试语句的部分,因为它们都成功了。此外,所有这些函数都在早期成功的测试中使用看起来很干净,1)减小测试输入大小2)尝试独立运行测试3)在remove_current
之后执行操作后检查originPtr.preducer和originPtr.cursor的行为实际的复制构造函数是Sequence::Sequence(const Sequence©Me){copy(copyMe);}
,它调用此函数是所有修复循环问题的函数,但会导致分段错误。请参见输出:我已将其更改为if
,而不是else if
,但仅此一项并没有任何区别。以下是删除当前():
和对副本的修复:
:。没有分段错误,但仍在loop@NP2000我的怀疑成真了。请看更新4
else if (originPtr == copyMe.precursor) { // consider removing 'else' here
Sequence copy2(original);
original.remove_current(); // here you remove the last element
void Sequence::remove_current() {
if (is_item()) {
node* temp;
temp = cursor;
if (cursor == headPtr && cursor == tailPtr) {
cursor = nullptr;
precursor = nullptr;
headPtr = nullptr;
tailPtr = nullptr;
}
else if (cursor == headPtr) {
headPtr = cursor->next;
cursor = headPtr;
precursor = nullptr;
}
else {
if (cursor == tailPtr) {
precursor->next = nullptr;
tailPtr = precursor;
cursor = precursor;
if (precursor == headPtr) {
precursor = nullptr;
}
else {
for(precursor = headPtr; precursor->next->next; precursor = precursor->next);
}
}
else {
precursor->next = cursor->next;
cursor = cursor->next;
}
}
delete temp;
numitems--;
}
}