如何替换链表中的新操作符

How to replace the new operator in linked list?

本文关键字:操作符 链表 何替换 替换      更新时间:2023-10-16

作为c++的新手,我正在尝试学习为什么以及在哪里使用new。所以我尽量不要在这个链表的例子中使用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,并且不使用它就无法完成。

我认为你不理解堆栈内存和堆内存。你应该做的事情被称为"动态分配"。

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

你不能按照你想要的方式去做,你似乎误解了内存在c++中的工作方式。使用指针和动态分配,这就是为什么他们称之为动态链表。

另外,不要用std:list作为你的问题,你写代码的方式告诉我,链表的实现是一种作业。在运行其他人的实现之前,先学习理解基本的功能。

如果没有new或某种形式的动态内存分配,就无法创建链表,因为您无法在堆栈上创建永久节点。

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

通过此操作

first = newlink;

你记录的数据超过旧数据。

您只有一个linklist类字段,并且在上面的每个操作中重写数据。

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

链表本质上是单个动态分配块的集合,因此new是必需的,无论它是否暴露给客户端代码。正如@Alok所建议的,std::list是可取的,因为它封装了这个内存分配,并确保没有泄漏发生,等等。在堆栈上分配newLink的尝试将导致编译失败,除非您获取其地址,而您当然不希望这样做(因为一旦函数返回,newLink将从堆栈中弹出)。

当你说

link newlink; //make a new link

你在堆栈上建立了一个链接,该链接将在函数结束时超出作用域。

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

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

堆栈

有许多文档深入解释了堆栈是什么。但是非常简单的堆栈内存是临时内存,它只在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;
}