我有双向链表,m_Terminal1是列表的开头,m_Terminal2是列表的结尾。这是我的代码
CBusLine(const CBusLine & orig){
m_Terminal1 = new TStop(orig.m_Terminal1 -> m_Name);
m_Terminal2 = new TStop(orig.m_Terminal1 -> m_Name);
TStop * tmpx = m_Terminal2;
TStop * copy = orig.m_Terminal1;
copy = copy ->m_Next;
while(copy != NULL){
TStop * copy_tmp = new TStop(copy->m_Name);
tmpx -> m_Next = copy_tmp;
copy_tmp -> m_Prev = tmpx;
tmpx = copy_tmp;
copy = copy->m_Next;
}
不幸的是,它不起作用,当我想打印出列表时,只有第一项。 这是源文件http://pastebin.com/YCKyZ31K。有人能帮助我吗?提前谢谢
答案 0 :(得分:0)
您正在创建两个与第一站(m_Terminal1
和m_Terminal2
)同名的对象,并将停靠列表添加到m_Terminal2
。因为变量指向内存中的不同位置(由new
调用提供),它们不是同一个项目,最后m_Terminal2
将具有完整列表,而m_Terminal1
只会有第一站。在此过程中,您不会将最后一站存储在m_Terminal2
。
解决此问题的一种方法是仅初始化并存储第一个停靠点,通过并添加所有停靠点,然后存储(不重新初始化)最后一个停靠点。
CBusLine(CBusLine & orig){
m_Terminal1 = new TStop(orig.m_Terminal1 -> m_Name);
TStop * tmpx = m_Terminal1;
TStop * copy = orig.m_Terminal1;
copy = copy ->m_Next;
while(copy != NULL){
TStop * copy_tmp = new TStop(copy->m_Name);
tmpx -> m_Next = copy_tmp;
copy_tmp -> m_Prev = tmpx;
tmpx = copy_tmp;
copy = copy->m_Next;
m_Terminal2 = tmpx;
}
答案 1 :(得分:0)
您应该重用已编写的代码。你写了一个Add()
函数,为什么不用呢?
首先,修复Add()函数,使其调用另一个函数,其唯一目的是在序列的末尾添加一个节点:
void CBusLine::Add(istream& is)
{
string line;
while(is.good())
{
getline(is, line);
if(line == "")
continue;
AddInternal(line);
}
}
void CBusLine::AddInternal(string& line)
{
TStop * n = new TStop(line);
if(m_Terminal2 == NULL){
m_Terminal1 = n;
m_Terminal2 = n;
}
else{
m_Terminal2 -> m_Next = n;
n -> m_Prev = m_Terminal2;
m_Terminal2 = n;
}
}
分解Add()函数的原因是,现在,复制构造函数(和赋值运算符)变得非常简单。
CBusLine(const CBusLine & orig)
{
TStop *startTerm = orig.m_Terminal1;
while ( startTerm != orig.m_Terminal2 )
{
AddInternal( startTerm->m_name);
startTerm = startTerm->m_Next;
}
}
当然,AddInternal必须正常工作。我假设m_Terminal1和m_Terminal2是链表的开头和结尾。
鉴于AddInternal()正常工作,复制构造函数是一个简单的循环,从开始到结束终端,并使用终端的字符串数据调用AddInternal()。这比在重新创建已在Add()函数中编写的代码更简单,逻辑上更有意义。
请注意,除了复制构造函数之外,还必须编写赋值运算符。