2016-09-27 118 views
1

在這個程序中,我完全理解爲什麼主函數的第一部分失敗並需要註釋 - 在我在TestingClass中實現值ctor後沒有隱式的默認ctor。完全合乎邏輯。但是,我發現第二部分(test2對象的創建)成功,至少在gcc 4.8.4中,我有點驚訝。沒有默認構造函數的初始化時的賦值

#include <iostream> 
using namespace std; 

class TestingClass 
{ 
    public: 
    TestingClass(int inVal) 
    { 
     val = inVal; 
    } 

    int val; 
}; 

TestingClass testingCreator() 
{ 
    return TestingClass(100); 
} 

int main() 
{ 
    /* 
    TestingClass test1; 
    test1 = testingCreator(); 
    cout << "Test1: " << test1.val << endl; 
    */ 

    TestingClass test2 = testingCreator(); 
    cout << "Test2: " << test2.val << endl; 
} 

關於它的思考,這也是情理之中,因爲對象,TEST2,以後再也沒有被修建/初始化存在,但大多數人在這種思維方式初始化爲只是做了聲明和賦值在一條線上。顯然,雖然初始化比這個更特別,因爲這個代碼有效。

這是標準C++嗎?它是否可以跨編譯器工作?我感興趣的是如何以這種方式初始化不同於聲明(使用默認ctor)然後賦值(通過在全局函數中創建的臨時對象)。

UPDATE:增加了一個副本ctor和明確使用copy ctor的第三種情況。

#include <iostream> 
using namespace std; 

class TestingClass 
{ 
    public: 
    TestingClass(const TestingClass &rhs) 
    { 
     cout << "In copy ctor" << endl; 
     this->val = rhs.val + 100; 
    } 
    TestingClass(int inVal) 
    { 
     val = inVal; 
    } 

    int val; 
}; 

TestingClass testingCreator() 
{ 
    return TestingClass(100); 
} 

int main() 
{ 
    /* 
    TestingClass test1; 
    test1 = testingCreator(); 
    cout << "Test1: " << test1.val << endl; 
    */ 

    TestingClass test2 = testingCreator(); 
    cout << "Test2: " << test2.val << endl; 

    TestingClass test3(test2); 
    cout << "Test3: " << test3.val << endl; 
} 

此輸出:

Test2: 100 
In copy ctor 
Test3: 200 
+0

「但是大多數人會這樣認爲初始化只是作爲一行中的聲明和賦值」......而不是大多數C++程序員。 (希望沒有任何!) –

回答

2

你對TestingClass test2 = testingCreator();做什麼的看法是有缺陷的。當你看到

type name = stuff; 

不創建name,然後分配給它stuff。你所做的是從stuff複製初始化name。這意味着您調用複製或移動構造函數。一般來說,這個調用可以通過優化編譯器來消除,但如果不是,那麼這就是你會看到的。無論哪種情況,都不會調用默認的構造函數。

在你的第一個例子

TestingClass test1; 

強制默認構造函數被調用,因爲你沒有一個你會得到一個錯誤。

+0

有趣的 - 我很清楚的複製ctor,只是不「看起來」像一個副本ctor調用 - 我通常認爲這是因爲當通過價值或當做更多明顯的「TestingClass test2(test3);」之類的事情。很快的答案 - 謝謝! – daroo

+0

但是 - 我只是更新了代碼,明確實現了一個複製ctor並在其中添加了一個打印語句。當我執行程序時,它不會打印。但是,如果我添加第三個測試「TestingClass test3(test2);」,字符串IS會打印出來。此外,我設置「this-> val = rhs.val + 100;」並且test2.val仍然被打印爲100,而不是200,而test3的值打印爲200. – daroo

+0

@daroo正如我所說的,編譯器擅長優化此操作,即使存在副作用,副本也會被忽略,並且唯一的構造函數被稱爲'TestingClass(int inVal)' – NathanOliver

0

test2是由TestingClass複製構造定義,取testingCreator作爲參數的結果。複製構造函數TestingClass::TestingClass(const TestingClass&)由編譯器自動生成,並且C++標準保證它複製val字段。

相關問題