2016-09-27 3 views
1

このプログラムでは、主関数の最初の部分が失敗し、コメントする必要があることを完全に理解しています - TestingClass内にctor値を実装した後に暗黙的なデフォルトctorはありません。完璧な論理。しかし、2番目の部分(test2オブジェクトの作成)が少なくともgcc 4.8.4ではうまくいくことがわかりました。デフォルトコンストラクタなしの初期化時の代入

オブジェクト、TEST2は、初期化/構築されずに存在しなかったでしょうが、ほとんどの人は単に宣言と代入であるとして、このように初期化を考えるので、それも理にかなって、それについて考える
#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; 
} 

1行に明らかに、このコードは機能するので、初期化はそれよりも特別です。

この標準はC++ですか?コンパイラ間で動作することは保証されていますか?私は、この方法での初期化が、(デフォルトのctorを使用して)宣言し、(グローバル関数で作成された一時オブジェクトを介して)代入する方法とは異なる点に興味があります。

UPDATE:コピーctorを追加し、コピーctorを明確に使用する3番目のケースを追加しました。

#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

"しかし、ほとんどの人はこのように初期化を1行の宣言と代入にすぎないと考えています" ...ほとんどのC++プログラマーはいません。 (うまくいけないことは全くありません!) –

答えて

2

TestingClass test2 = testingCreator();の考え方には欠陥があります。あなたは

type name = stuff; 

が表示されたらあなたはnameを作成し、それstuffに割り当てないでください。コピーをコピーするのはnameからstuffまでです。つまり、コピーまたは移動コンストラクタを呼び出します。一般に、この呼び出しはコンパイラを最適化することによって省略することができますが、そうでなければ、それはあなたが見るものです。どちらの場合でも、デフォルトのコンストラクタは決して呼び出されません。あなたの最初の例で

TestingClass test1; 

は、デフォルトコンストラクタが呼ばれるように強制的に、あなたは1を持っていないので、エラーが発生します。

+0

興味深い - 私はコピーctorをよく知っています。それはコピーctorコールのように "見た目"ではありません - 私は通常、値渡しや明らかに "TestingClass test2(test3);"ものの種類。素晴らしい素早い答え - ありがとう! – daroo

+0

しかし、私は、コードを明示的に実装してそこにprintステートメントを追加するようにコードを更新しました。プログラムを実行すると印刷されません。しかし、3番目のテスト "TestingClass test3(test2);"を追加すると、文字列ISが出力されます。さらに、私は "this-> val = rhs.val + 100;"を設定します。 test3の値は200として表示されますが、test2.valは200ではなく100として表示されます。 – daroo

+0

@darooこれは、コンパイラがこれを最適化するのに効果的だと言いましたが、副作用があってもコピーは省略され、 'TestingClass(int inVal)'と呼ばれています – NathanOliver

0

test2は、引数としてtestingCreatorの結果を取って、TestingClassのコピーコンストラクタで定義されています。コピーコンストラクタTestingClass::TestingClass(const TestingClass&)はコンパイラによって自動的に生成され、C++標準ではvalフィールドがコピーされることが保証されています。

関連する問題