如何替换链表中的新运算符?

时间:2013-06-10 16:29:31

标签: c++

作为c ++的新角色,我试图了解使用New的原因和位置。 所以我试图在这个链接的List例子中不使用New,

////////////////////////////////////////////////////////////////
struct link //one element of list
{
    int data; //data item
    link* next; //pointer to next link
};
////////////////////////////////////////////////////////////////
class linklist //a list of links
{
private:
    link* first; //pointer to first link
public:
    linklist() //no-argument constructor
    { first = NULL; } //no first link
    void additem(int d); //add data item (one link)
    void display(); //display all links
};
//--------------------------------------------------------------
void linklist::additem(int d) //add data item
{
    link* newlink = new link; //make a new link
    newlink->data = d; //give it data
    newlink->next = first; //it points to next link
    first = newlink; //now first points to this
}
//--------------------------------------------------------------
void linklist::display() //display all links
{
    link* current = first; //set ptr to first link
    while( current != NULL ) //quit on last link
    {
        cout << current->data << endl; //print data
        current = current->next; //move to next link
    }
}
////////////////////////////////////////////////////////////////
int main()
{
    linklist li; //make linked list
    li.additem(25); //add four items to list
    li.additem(36);
    li.additem(49);
    li.additem(64);

    return 0;
}

以下内容:

 ////////////////////////////////////////////////////////////////
struct link //one element of list
{
    int data; //data item
    link* next; //pointer to next link
};
////////////////////////////////////////////////////////////////
class linklist //a list of links
{
private:
    link first; //pointer to first link
public:
    linklist() //no-argument constructor
    { first = NULL; } //no first link
    void additem(int d); //add data item (one link)
    void display(); //display all links
};
//--------------------------------------------------------------
void linklist::additem(int d) //add data item
{
    link newlink; //make a new link
    newlink.data = d; //give it data
    newlink.next = first; //it points to next link
    first = newlink; //now first points to this
}
//--------------------------------------------------------------
void linklist::display() //display all links
{
    link current = first; //set ptr to first link
    while( current != NULL ) //quit on last link
    {
        cout << current.data << endl; //print data
        current = current.next; //move to next link
    }
}
////////////////////////////////////////////////////////////////
int main()
{
    linklist li; //make linked list
    li.additem(25); //add four items to list
    li.additem(36);
    li.additem(49);
    li.additem(64);
    return 0;
}

但这不起作用。在我继续尝试之前,我想知道这个特定的例子是否必须坚持使用New,而不使用它就无法完成。

6 个答案:

答案 0 :(得分:2)

无法在没有new或某种形式的动态内存分配的情况下创建链接列表,因为您无法创建指向堆栈的永久节点。

但是,幸运的是,您不必自己编写容易出错的new代码,因为C ++已经为您提供了一个方便的std::list类。另外,在C ++ 11中提供了单独链接的forward_list

答案 1 :(得分:2)

我认为你不了解堆栈内存与堆内存。你应该做的是“动态分配”。

如果您将变量定义为link newlink; 你只在堆栈上创建它,这意味着当你退出你的函数时它不再存在,它被“解除分配”。该列表所需的是请求在完成功能时未释放的新内存区域。为此,您需要使用动态分配。其中一种方法是new运算符。另一种规范的做法是malloc函数。

TL; DR你不能按照你想要的方式去做,你似乎误解了C / C ++中的内存是如何工作的。您 使用指针和动态分配,这就是他们称之为动态链接列表的原因。

另外,不要使用std:list作为你的问题,你编写代码的方式指向我,链表实现是各种各样的功课。在跑向其他人的实施之前,先学习理解基本功能。

答案 2 :(得分:0)

通过此行动

first = newlink;

您在旧数据上记录数据。

您只有一个linklist类字段,并在上面的每个操作都覆盖数据。

当您使用new时,它会在堆中(在linklist之外)分配实例,并且这些实例(link)通过指针相互连接。在你的第二段代码中,它没有发生,你在内存中只有一个link的实例。

答案 3 :(得分:0)

链接列表本质上是各个动态分配的块的集合,因此new是一个要求,无论它是否暴露给客户端代码。正如@Alok建议的那样,std::list更可取,因为它封装了这个内存分配并确保不会发生泄漏等。你在堆栈上分配newLink的尝试将无法编译,除非你取其地址,您当然不想这样做(因为newLink将在函数返回后立即从堆栈中弹出。)

答案 4 :(得分:0)

当你说

link newlink; //make a new link

你已经在堆栈上建立了一个超出范围的链接。

我认为你应该使用规则“避免原始指针”,而不是避免新的。如果你使用std :: make_shared,并保持std :: unique_ptr而不是原始指针,这可能是一个有用的学习练习。

答案 5 :(得分:0)

要解决您的问题,您必须先了解以下内容:

堆栈

有许多文档深入解释了堆栈是什么。但非常简化的堆栈内存是临时内存,只能在c ++的范围内使用。例如:

int* p;
{
   int a; //Create a variable in stack memory
   a = 10; //Assing stack memory
   p = &a; //Create a pointer to stack memory
} //Variable a is released since the scope has ended

printf("%d",*p); //The pointer now points to released memory. Probably it will not be 10

这同样适用于以下功能:

void suma()
{
    int a; //This variable will only exists for this function
}

您的代码

您正在做的是创建和复制稍后将在函数结束时释放的变量。

link first; //pointer to first link

void linklist::additem(int d) //add data item
{
    link newlink; //I'll only exists in this function
    newlink.data = d; 
    newlink.next = first; //Does even this compiles???
    first = newlink;  //After the function sends first will point to a released memory. Aren't you missing a & operator ? &newlink
}

解决方案

您需要将链接节点存储在某处。新运营商为您做到了这一点。但如果你不想使用它。您可以将其存储在静态存储器中。

例如,你可以有两个这样的静态变量:

link staticLinks[100];
int lastUsedLink = 0;

在整个程序执行期间不会释放此内存,因此您可以执行以下操作:

void linklist::additem(int d) //add data item
{
    staticLinks[lastUsedLink].data = d; //Now this data will no dissapear
    lastUsedLink[lastUsedLink].next = first; //Point to the last element
    first = &lastUsedLink[lastUsedLink]; //No this becomes the last element
    lastUsedLink++; //Use the next element of the array for the next addition
}

它非常容易改进。例如,您可以添加一个防护,以避免使用101或更多数组元素。但现在你可能会理解这个问题了。

完整代码##

////////////////////////////////////////////////////////////////
struct link //one element of list
{
    int data; //data item
    link* next; //pointer to next link
};

link staticLinks[100];
int lastUsedLink = 0;

////////////////////////////////////////////////////////////////
class linklist //a list of links
{
private:
    link* first; //pointer to first link
public:
    linklist() //no-argument constructor
    { first = NULL; } //no first link
    void additem(int d); //add data item (one link)
    void display(); //display all links
};
//--------------------------------------------------------------
void linklist::additem(int d) //add data item
{
    staticLinks[lastUsedLink].data = d; //give it data
    lastUsedLink[lastUsedLink].next = first; //it points to next link
    first = &lastUsedLink[lastUsedLink]; //now first points to this
    lastUsedLink++;
}
//--------------------------------------------------------------
void linklist::display() //display all links
{
    link current = first; //set ptr to first link
    while( current != NULL ) //quit on last link
    {
        cout << current.data << endl; //print data
        current = current.next; //move to next link
    }
}
////////////////////////////////////////////////////////////////
int main()
{
    linklist li; //make linked list
    li.additem(25); //add four items to list
    li.additem(36);
    li.additem(49);
    li.additem(64);
    return 0;
}