2013-06-01 14 views
0

C++構造函數和澄清,我問發生對類實例化​​一些混亂的問題。對於如何實例

如果你有一個類A(),如:

class A 
{ 
public: 
    A(); 
    ~A(); 
}; 

然後我想與該類工作,以下所有的可以做:

// First way 
A a1; 
// Second way 
A a1 = A(); 
// Third way 
A::A a1 = A::A(); 
// Fourth way 
A* a1 = new A(); 

我被告知,第三種方式A::A a1 = A::A();是不合適的,但它似乎工作。

任何人都可以解釋所有這些方式以及何時使用一個比其他?我認爲new分配在堆而不是堆棧?

實施例的程序:

#include <iostream> 
#include <string> 

class A 
{ 
    public: 
    A(); 
    ~A(); 
}; 

A::A() 
{ 
    std::cout << "A" << std::endl; 
} 

A::~A() {} 

int main() 
{ 
    A a1; 

    A a2 = A(); 

    A::A a3 = A::A(); 

    A* a4 = new A(); 

    return 0; 
} 

輸出:

$ ./test4 
A 
A 
A 
A 

所以在克++ 4.2它的工作。

$ g++ -Wall main3.cpp -o test4 
main3.cpp: In function ‘int main()’: 
main3.cpp:28: warning: unused variable ‘a4’ 

在GCC 4.8,與其說:

g++-4.8 -std=c++11 -Wall main3.cpp -o test4 
main3.cpp: In function ‘int main()’: 
main3.cpp:26:2: error: ‘A::A’ names the constructor, not the type 
A::A a3 = A::A(); 
^ 
main3.cpp:26:7: error: expected ‘;’ before ‘a3’ 
    A::A a3 = A::A(); 
    ^
main3.cpp:26:18: error: statement cannot resolve address of overloaded function 
    A::A a3 = A::A(); 
      ^
main3.cpp:28:8: warning: unused variable ‘a4’ [-Wunused-variable] 
    A* a4 = new A(); 
     ^
+5

問這裏是錯誤的,因爲我們只能花幾分鐘回答你的問題。最好花幾個小時來學習一本好的C++編程書。 C++是一門難以學習的語言,你需要很多小時才能完成。此外,使用編譯器啓用調試信息和警告(例如,在Linux上用'g ++ -Wall -g'編譯)並學習使用調試器(Linux上的'gdb')。 –

+0

我不認爲第三種形式有效([示例](http://coliru.stacked-crooked.com/view?id=3c6b93406db9ef317b83a5f19c79a30d-e54ee7a04e4b807da0930236d4cc94dc))。 –

+0

@安迪,謝謝你。我促使我嘗試g ++ 4.2和4.8,看看上面的更新。 – Jason

回答

0

爲對象的前兩個版本是相同的(正式,第二包括另一個副本,但那是由任何編譯器稱職的優化掉)。然而,有些情況下,他們是不相同的對象:

如果你沒有編寫自己的默認構造函數(即使是空的)和對象不有靜態存儲時間(在你的代碼,它具有自動存儲持續時間),第一個版本不會初始化任何POD成員,而第二個版本會在任何情況下將它們初始化爲零。另一方面,如果您的類不支持複製(您明確地將複製構造函數設置爲私有的,或者在C++ 11中刪除它,並且也沒有提供移動構造函數),那麼第二種形式將是不合格的(即使該副本不實際發生,邏輯上它在那裏)。

您的第三種形式不是合法的C++;如果你的編譯器接受它,它可能是一個錯誤或一個非標準的擴展(儘管我敢打賭一個錯誤)。

第四種形式不動態分配,即您有責任明確銷燬它(使用delete a4;)。另請注意,存儲在a4中的內容不是對象本身,而是指向它的指針;這意味着要訪問對象,你必須明確地解引用指針。

請注意,自從C++ 11以來,有一種新的初始化形式,這對於空參數列表尤其適用,因爲它結合了前兩個版本的優點:它也適用於不可複製/不可移動對象,並初始化PODs:

A a5{}; 
+0

實際上,如果'A'命名了有效的命名空間,則第三種形式是合法的。 – greatwolf

+0

@greatwolf:它不在給定的示例程序中。 – celtschk

+0

只是想我會提到它,因爲它可能會誤導OP,認爲這不是合法的C++語法。 – greatwolf

0

首屆初始化a1使用默認構造函數。

第二個首先使用默認構造函數初始化a2,然後將通過明確調用創建的對象分配給默認構造函數。

我不認爲第三形式的作品,所以我離開它。

最後一個分配適當大小的存儲器來存儲類A的一個對象,並初始化使用調用的構造函數分配的內存(默認構造函數你的情況)。

0

你應該學會動態和靜態分配的區別。除此之外,第一種形式是你想要使用的,因爲它隱式地調用了默認的構造函數。在第二種形式中,您正在創建A類的臨時實例並使用其自動生成的拷貝構造函數創建a1,但大多數編譯器只會將其優化爲a1的單個默認構造。第三種形式僅僅是無效的C++。第四種形式是執行動態分配,並且您沒有正確地使用刪除來釋放內存,所以當程序退出時,您已將它留給操作系統來回收內存。