Как заменить новый оператор в связанном списке?

Как новый участник c++, я пытаюсь узнать, почему и где использовать 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 и не может быть выполнен без его использования.

-4
10 июня '13 в 19:29
источник поделиться
6 ответов

Я думаю, что вы не понимаете стек стек и память кучи. То, что вы должны сделать, называется "динамическое распределение".

Если вы определяете переменную как link newlink; вы создаете его только в стеке, а это означает, что когда вы выходите из своей функции, он больше не существует, он "освобождается". Что вам нужно для этого списка - запросить новую область памяти, которая не будет освобождена при завершении вашей функции. Для этого вам нужно использовать динамическое распределение. Одним из способов этого является new оператор. Другим каноническим способом является функция malloc.

TL; DR Вы не можете сделать это так, как хотите, вы, похоже, неправильно поняли, как работает память в C\C++. Вы должны использовать указатели и динамическое распределение, поэтому они называют его динамическим связанным списком.

Кроме того, не используйте std: list в качестве вашего вопроса и способ, которым вы пишете свои кодовые точки, для меня, что реализация связанного списка является домашним заданием. Научитесь понимать базовые функциональные возможности перед запуском для реализации других людей.

2
10 июня '13 в 19:40
источник

Связанный список не может быть создан без new или какой-либо формы распределения динамической памяти, потому что вы не можете создавать постоянные узлы, указывающие на стек.

Однако, к счастью, вам не нужно самостоятельно писать new код, подверженный ошибкам, потому что C++ предоставляет вам удобный класс std::list. Кроме того, в forward_list C++ имеется отдельный связанный forward_list.

2
10 июня '13 в 19:38
источник

Связанный список, по сути, представляет собой набор отдельных динамически распределенных блоков, поэтому new - это требование, независимо от того, подвергается ли он клиенту или нет. Как и @Alok, рекомендуется, чтобы std::list был предпочтительнее, поскольку он инкапсулирует это распределение памяти и гарантирует отсутствие утечек и т.д. Ваша попытка выделить newLink в стеке не будет компиляции, если вы не возьмете ее адрес, который вы, конечно, (так как newLink будет newLink из стека, как только функция вернется).

0
10 июня '13 в 19:39
источник

Когда ты говоришь

link newlink; //make a new link

вы сделали ссылку на стек, который выйдет за пределы области действия к концу функции.

Я думаю, вы должны использовать правило "избегать необработанных указателей", а не избегать новых. Если вместо этого вы используете std :: make_shared и держите std :: unique_ptr вместо необработанных указателей, которые могут быть полезным упражнением по обучению.

0
10 июня '13 в 19:54
источник

Этим действием

first = newlink;

вы записываете данные по старым данным.

У вас есть только одно поле класса linklist и переопределение данных при каждом действии выше.

Когда вы используете new, он выделяет экземпляры в куче (вне linklist) и эти экземпляры (link), связанные друг с другом указателями. В вашей второй части кода это не происходит, и у вас в памяти только один экземпляр link.

0
10 июня '13 в 19:37
источник

Чтобы решить вашу проблему, вы должны понимать следующее:

Стек

Есть много документов, которые подробно объясняют, что такое стек. Но очень упрощенная память стека - это временная память, доступная только в пределах области действия 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;
}
0
10 июня '13 в 20:00
источник

Посмотрите другие вопросы по метке или Задайте вопрос