2014-11-04 114 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; 
} 

從什麼IVE讀,使用所述第一方式中,變量是在堆上分配,並且第二,在堆棧中,但的arent兩者Main範圍內,並在函數退出後解除分配?

此外,兩種示例中的調用方法都不相同,爲什麼

+0

感謝編輯@remyabel,這種方式更好,它避免了混淆。 – Leandragem 2014-11-05 00:02:11

+0

你似乎對C++的理解很少。在問這樣的超級基本問題之前,你應該先做一些研究或讀一本書。這是C++ 101 – Falmarri 2014-11-05 00:02:59

+0

那麼你是對的。我是C++的新手,但在繼續下一步之前,我試圖更好地理解這些主題。你會推薦一個很好的C++閱讀材料嗎? – Leandragem 2014-11-05 00:04:18

回答

1

您的權利這兩個變量都在Main範圍和功能退出後釋放,但在第一種情況下它是Test*值被釋放,而不是Test實例本身。一旦指針解除分配,類實例就會泄露。在第二種情況下,Test實例位於堆棧上,因此實例本身已解除分配。

此外,調用方法在兩個示例中都不相同,爲什麼?

除非超載,foo->bar相當於(*foo).bar。調用語法不同,因爲在第一種情況下,test1是指向實例的指針,而第二種情況下,test2是一個實例。

1

但不是都在主範圍內,並在 函數退出後被釋放?

完全沒有...... * test1在你調用delete之前不會被釋放。

+0

你不是指'test1'嗎? – 2014-11-05 00:02:50

1

但都沒有在主範圍內,並在函數退出後被釋放?

隨着作用域關閉並釋放,棧實例解除展開。指針也是,但它指向的對象不是。您必須明確delete實例分配與new

1

在第一個示例中,您正在創建一個指向堆棧上的對象的指針,以及堆中的對象本身。

在第二個示例中,您正在堆棧上創建對象本身。

語法區別是通過指針調用函數並直接在對象上調用函數的區別。

對於正在清理的第一個示例,在指針超出範圍之前需要一個delete或者出現所謂的內存泄漏,這是錯誤的。當程序退出時,操作系統會清理內存泄漏,但最好的做法是避免它們。

+0

感謝您的回覆。對此有沒有「最佳實踐」?像什麼時候使用一個或另一個? – Leandragem 2014-11-05 00:06:37

+2

@Leandragem使用本地(堆棧)對象,除非您需要該對象的生存期超出當前塊的存在,或者如果您將該對象的所有權傳遞給其他人。或者有時如果你需要一個不適合堆疊的大對象或數組,例如數百萬的元素。 – 2014-11-05 00:08:38

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 kb的內存,但您無法訪問。

的解決辦法是改變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 2014-11-05 00:31:06

+0

@大衛這是一個很好的觀點。相應的更改。 – Galik 2014-11-05 01:34:23

0

,如果你不出來的主之前刪除的Test1(測試*),就會造成內存泄漏。