2016-10-19 4 views
2

Пожалуйста, обратитесь код, указанный здесь:разница между использованием и не использованием нового указателя

Этот код является частью реализации стека в C++:

Код 1:

void Stack::pop() 
{ 
    if (top != 0) { 
     node* temp = top; 
     top = top -> link; 
     delete temp; 
    } 
} 

Код 2:

В первом примере я не использовал новый, в то время как я использовал его во втором. На беге, оба дают то же результат с полной программой, которую можно найти ниже:

#include <iostream> 

using namespace std; 

struct node { 
    string name; 
    node* link; 
}; 

class Stack 
{ 
    node* top; 
public: 
    Stack(); 
    void push(string s); 
    void pop(); 
    void display(); 
    ~Stack(){} 
}; 

Stack::Stack() { 
    top = 0; 
} 

void Stack::push(string s) 
{ 
    node* temp = new node; 
    temp -> name = s; 
    temp -> link = top; 
    top = temp; 
} 

void Stack::pop() // Function in question 
{ 
    if (top != 0) { 
     node* temp = new node; 
     temp = top; 
     top = top -> link; 
     delete temp; 
    } 
} 

void Stack::display() 
{ 
    node* temp = new node; 
    temp = top; 
    while (temp != 0) 
    { 
     cout << temp -> name << "\n"; 
     temp = temp -> link; 
    } 
} 

int main() { 
    Stack s; 
    s.push("Ra"); 
    s.push("Sa"); 
    s.push("Ga"); 
    s.pop(); 
    s.display(); 
} 

Что такое разницы в использовании и не используя новый указателя здесь?

Также автоматически ли освобождается память или я должен делать это в деструкторе? Если да, то как это сделать?

+0

@Abhineet Извините, что не нашёл это полезным – samjoe

ответ

5

Утечка памяти во втором фрагменте кода, хотя она хорошо работает. new node не имеет значения для node* temp = new node;, потому что temp присваивается top сразу. Затем исходный адрес памяти, созданный new node, теряется и не может быть delete d снова.

Также автоматически ли автоматически освобождается память или я должен делать это в деструкторе?

Каждый объект new ed должен быть delete d самостоятельно. Подумайте о smart pointers, они будут управлять такими вещами для вас.

+0

Почему он не может быть удален снова? Что случилось? – samjoe

+0

@samjoe Потому что он потерян. – songyuanyao

+0

Эй, это я дал ему другое место после объявления? То есть исходное местоположение, которое было выделено, потеряно, и я дал ему новый адрес? – samjoe

3

В этих строках:

node* temp = new node; 
    temp = top; 

вы выделяете новый узел, храните его в temp переменной и т следующей переменной хранить в одной и той же переменной другой указатель. Так что новый узел теряется и используется более новый. node* temp = new node; не имеет никакого эффекта, кроме утечки памяти.

Также автоматически освобождается память или я должен ее сделать в деструкторе?

No. Память не освобождается автоматически. И вы почти никогда не называете деструктор объекта вручную.

Если да, то как это сделать?

Старый способ заключается в использовании delete. Но в современном C++ вы не должны использовать голые указатели владения и действительно должны рассмотреть возможность использования std::unique_ptr.

+0

Я думаю, что лучше использовать std :: shared_ptr для реализации становится проще при назначении и копировании shared_ptrs –

+0

С 'unique_ptr' вы всегда знаете, кому принадлежит этот объект. Это придает порядок программам и порядку, что хорошо для читаемости и стабильности. С 'shared_ptr' вы можете случайно создать циклы и сделать ваш код более сложным. 'shared_ptr' неплохие, но их нельзя использовать везде. Кроме того, 'unique_ptr' - более легкая конструкция. –

+0

Согласен. Но как вы пройдете через связанный список, если его ссылки уникальны? –

2

При использовании нового/выделения памяти вы вызываете утечку памяти.

node* temp = new node; 
temp = top; //temp is now pointing to a new memory location. 
      //Thus the memory allocated by in the previous code line gets leaked 

Код1 - правильный способ сделать это. Код 2 вызывает утечку памяти.

Вы должны удалить выделенную память, используя оператор delete в деструкторе.

Stack::~Stack() 
{ 
    while(NULL != top) 
    { 
     node* temp = top; 
     top = top->link; 
     delete temp; 
    } 
} 

Умный указатель Решение. Для компиляции/работы вам понадобится компилятор C++ 11 для следующего кода.

#include <iostream> 
#include <memory> 

using namespace std; 

struct node { 
    string name; 
    std::unique_ptr<node> link; 
};  
typedef std::unique_ptr<node> node_ptr; 

class Stack 
{ 
    node_ptr top; 
public: 
    Stack(); 
    void push(string s); 
    void pop(); 
    void display(); 
    ~Stack(){} 
}; 

Stack::Stack() { 
} 

void Stack::push(string s) 
{ 
    auto temp = std::make_unique<node>(); 
    temp -> name = s; 
    temp -> link = top; 
    top = temp; 
} 

void Stack::pop() 
{ 
    if (top != null) { 
     top = top -> link; 
    } 
} 

void Stack::display() const 
{ 
    node* temp = top.get(); 
    while (temp != 0) 
    { 
     cout << temp -> name << "\n"; 
     temp = (temp -> link).get(); 
    } 
} 

int main() { 
    Stack s; 
    s.push("Ra"); 
    s.push("Sa"); 
    s.push("Ga"); 
    s.pop(); 
    s.display(); 
}