2016-02-28 9 views
6

戻り値の型を構築するための明示的なコンストラクタを使用することはできません来るので、私はこのクラスの作成:は、どのように私は明示的なコンストラクタとその動作で遊ん

#include <iostream> 

class X 
{ 
public: 
    explicit X(void) 
    { 
     std::cout << "Default constructor\n"; 
    } 
    explicit X(X const& x) 
    { 
     std::cout << "Copy constructor\n"; 
    } 
    explicit X(X&& x) 
    { 
     std::cout << "Move constructor\n"; 
    } 
}; 

基本的に明示的なテストするための単なるスタブですコンストラクタ。 次に、私はいくつかの状況を試してみたかったのです。だから私はこの試みた:

X foo(void) 
{ 
    X a{}; 
    return a; // ERROR: no matching constructor found! 
} 

int main() 
{ 
    X w{}; // Default Constructor 
    X x{w}; // Copy Constructor 
    X y{std::move(x)}; // Move Constructor 
    X z{foo()}; 
} 

をそして、あなたが見ることができるように私はfoo()aを返すことができません。コピーコンストラクタで戻り値の型Fooを初期化しようとしていますが、何らかの理由でそれを使用できません。

提供されたコピーコンストラクタを使用できないのはどうしてですか? explicit仕様では、コピーコンストラクタから削除すると問題が発生することがわかりました。しかし、なぜ?

何でももっと私を混乱することは、私は次の操作を行うことができるということです。

void bar(const X& a) { /* */ } 
bar(X{}); 

それは文句はありません。しかし、bar()のパラメータをaと同じにするべきではありません。foo()と同じ方法で戻り値を構成しますか?

+1

'bar'を呼び出すとコンストラクタがまったく呼び出されず、参照(ポインタ)が渡されます。コピーされていないコンストラクタが呼び出されるはずです。 –

答えて

5

。しかし、コピーコンストラクタにはexplicitというマークが付けられているため、許可されていません。

コピー/移動コンストラクタをマークする理由がないのは確かですexplicit

+0

でも 'void bar(const X&a)'を定義してこの 'bar(X {});'のように使うことができます。これも暗黙のコピーではありませんか? – hgiesel

+0

@henrikgieselいいえ。 'a'は参照です。一時的な' X {} 'にバインドしているだけです。 – Barry

+0

さて、私は 'X&foo()'を書き直したときについにその画像を手に入れました。 (もちろん、それはばかですが、何が起こっていたのか理解するのに役立ちました) – hgiesel

0

明示的に宣言したときにコンパイラが暗黙的に使用しないようにすることはできません。

explicit X(X const& x) 

ただし、xを戻り値にコピーする必要があります。

X(X const& x) 

に変更してください。すべて動作します。

X foo() 
{ 
    X a{}; 
    return a; 
} 

あなたが暗黙的にfooの復帰にaをコピーしている:あなたはfooから戻ってきているとき

Live on Coliru

+0

* "コピーコンストラクタから削除しても動作するので、明示的な仕様で問題が発生することがわかりますが、なぜですか?" * - OP。 – LogicStuff

+1

つまり、地獄では 'foo()'に元の 'Foo'オブジェクトを返すことはできません。 – hgiesel

+0

とにかく '明示的に'働くようにするには? –

1

あなたはexplicitの意味を誤解していると思います。 explicitコンストラクタは、暗黙の型変換/ CASTSには使用されません。これは、すでに暗黙的にコピーコンストラクタを使用しないようにコンパイラに指示しましたので、

X foo(void){ 
    X a{}; 
    return a; // ERROR: no matching constructor found! 
} 

がコンパイルされないことを意味します。

あなたが達成したいのは、コピーではなく、「移動」であると思います。a。クラスに(通常の)移動コンストラクタがある限り、aはコピーされずに移動されますが、これがデフォルトの動作です。実際には、C++ 99でも、ほとんどのコンパイラはこのコピーを最適化するのに十分なほど巧妙です。

関連する問題