2014-11-04 3 views
0

В чем разница между этими двумя типами создания экземпляров и методов?Методы создания объектов в C++

Возьмите этот код, например:

class Test 
{ 
public: 
    Test(int nrInstance) 
    { 
     std::cout << "Class " << nrInstance << " instanced " << std::endl; 

    } 

    ~Test() { } 

    int retornaValue() 
    { 
     return value; 

    } 

private: 
    const int value = 10; 

}; 


int main(int argc, char *argv[]) 
{ 
    Test *test1 = new Test(1); 
    Test test2(2); 

    std::cout << test1->retornaValue() << std::endl; 
    std::cout << test2.retornaValue() << std::endl; 

    return 0; 
} 

Из того, что ив читать, используя первый способ, переменная выделяется в куче, а во-вторых, в стеке, но Арент как внутри Main сферы , и освобождается после выхода функции?

Кроме того, вызывающие методы в обоих примерах различны, почему?

+0

Спасибо за редактирование @remyabel, этот способ лучше, он избегает путаницы. – Leandragem

+0

У вас мало понимания C++. Вы должны, вероятно, провести некоторое исследование или прочитать книгу, прежде чем задавать такие основные вопросы. Это C++ 101 – Falmarri

+0

Ну, ты прав. Я новичок в C++, но я пытаюсь лучше понять эти темы, прежде чем перейти к следующему шагу. Вы порекомендовали бы хороший материал для чтения для C++? – Leandragem

ответ

1

Ваше право, что обе переменные в Main объеме и высвобождены после функциональных выходов, но в первом случае это Test* значение, освобождаться, а не сам Test экземпляр. Как только указатель будет освобожден, экземпляр класса просочится. Во втором случае экземпляр Test находится в стеке, поэтому сам экземпляр освобождается.

Кроме того, методы вызова в обоих примерах различны, почему?

Если перегруженный, foo->bar эквивалентен (*foo).bar. Вызывающий синтаксис отличается тем, что в первом случае test1 является указателем на экземпляр, а во втором - test2.

1

но arent как внутри основной области, так и освобождение после функция выхода?

Нет, совсем нет ... * test1 не будет освобожден, пока вы не назовете на него delete.

+0

Вы не имеете в виду 'test1'? –

1

но arent как внутри основной области, так и освобождается после выхода функции?

Экземпляр стека разматывается, когда область действия закрыта и, следовательно, освобождена. Указатель также есть, но объект, который он указывает на , не является. Вы должны явно указать delete экземпляров, выделенных new.

1

В первом примере вы создаете как указатель на объект в стеке, так и сам объект в куче.

Во втором примере вы создаете сам объект в стеке.

Разница в синтаксисе - это разница между вызовом функции через указатель и вызовом ее непосредственно на объект.

Вы ошибаетесь в том, что первый очищаемый пример вам нужен delete до того, как указатель выходит из сферы действия или у вас есть то, что известно как утечка памяти. Утечки памяти будут очищены ОС при выходе из программы, но хорошая практика - избежать их.

+0

Спасибо за ответ. Есть ли «лучшие оценки» в этом отношении? Как, когда использовать тот или иной? – Leandragem

+2

@Leandragem использует локальный (стек) объект, если вам не требуется время жизни объекта, находящегося за пределами текущего блока, или если вы передаете право собственности на объект на что-то другое. Или иногда, если вам нужен большой объект или массив, который не поместится в стеке, например. миллионы элементов. –

1

Вы четко указали разницу в своем вопросе, один находится в стеке, а один находится в куче.И да, когда main() выходов, он будет освобожден. Теперь давайте возьмем другой подход.

#include <iostream> 
using namespace std; 

class MemoryLeak{ 
    private: 
     int m_instance 
    public: 
     MemoryLeak(int i) : m_instance(i) 
      { cout << "MemoryLeak " << i << " created.\n"; } 
     ~MemoryLeak() { cout << "MemoryLeak " << m_instance << " deleted.\n"; } 
}; 

void makeMemoryLeak(){ 
    static int instance = 0 
    MemoryLeak mem1(++instance); 
    MemoryLeak* mem2 = new MemoryLeak(++instance); 
} 

int main(){ 
    for(int x = 0; x < 10; ++x){ 
     makeMemoryLeak(); 
     cout << endl; 
    } 

    cin.get(); // Wait to close 

    return 0; 
} 

Вы увидите 20 «Новый созданный MemoryLeak». линии, но только 10 «MemoryLeak deleted» линий. Таким образом, все остальные 10 экземпляров все еще находятся в памяти, пока вы не закроете программу. Теперь предположим, что эта программа никогда не выключается, а MemoryLeak имеет размер 20 байтов. и makeMemoryLeak() работает один раз в минуту. Через один день, или 1440 минут, у вас будет 28.125 килобайт памяти, которая будет поднята, но у вас нет доступа.

решение было бы изменить makeMemoryLeak()

void makeMemoryLeak(){ 
    MemoryLeak mem1; 
    MemoryLeak* mem2 = new MemoryLeak(); 
    delete mem2; 
} 
1

Что касается того, что будет создаваться и уничтожено:

struct Test {}; 

void func() 
{ 
    // instantiate ONE automatic object (on the stack) [test1] 
    Test test1; 

    // Instantiate ONE automatic object (on the stack) [test2] 
    // AND instantiate ONE object from the free store (heap) [unnamed] 
    Test* test2 = new Test; // two objects!! 

} // BOTH automatic variables are destroyed (test1 & test2) but the 
    // unnamed object created with new (that test2 was pointing at) 
    // is NOT destroyed (memory leak) 
+0

Поскольку вы выходите из main, * test2 ** ** уничтожается. Как только вы выйдете из своей программы, ОС очистит любую выделенную память. Если вы делаете что-то похожее на мой ответ, это показывает, как он не удаляется. – David

+0

@ Давид Это очень хороший момент. Соответственно сделаны изменения. – Galik

0

если вы не удалите Test1 (Test *) перед выходом из основной, это приведет к утечка памяти.

Смежные вопросы