2017-08-08 13 views
14

ルック:クラスの戻り値の型を持つ関数内のreturn文で*&オブジェクトを返すときに、コピー/移動エリーションは許可されていますか?このコードでは

:許可/移動エリジオンをコピー

#include <stdio.h> 

struct Foo { 
    Foo() { } 
    Foo(const Foo &) { printf("copy\n"); } 
    Foo(Foo &&) { printf("move\n"); } 
}; 

Foo getFoo() { 
    Foo f; 
    return *&f; 
} 

int main() { 
    getFoo(); 
} 

C++ 14標準が言う(12.8/31) 式が、ファンクションの戻り値の型として同じ型の 型の不揮発性自動オブジェクト( ファンクションまたはキャッチ節パラメータ以外)の名前である場合、コピー/移動操作は を省略することができます自動的にオブジェクトをに直接組み込むことによって関数の戻り値

私の例では、戻り式は名前ではないため、elisionは許可されていません。

私はGCC/clang/MSVCをチェックしていますが、clang/MSVCはコピーを消去しませんが、GCCはそれを行います。 GCCはここで標準に違反していますか?

+0

なぜコンパイラが、 'と'& '演算子です。また、どのバージョンのコンパイラを使用していますか? C++ 14モードでビルドしていますか?また、標準を引用するときは、コードの元の場所(名前または章番号/セクション番号)を明記してください。 –

+0

全く関係のないメモで、なぜあなたは出力に 'printf'を使用していますか?なぜ 'std :: cout'ではないのですか? –

+2

@Someprogrammerdude - コンパイラは、おそらくそれらを放出されたコードに保持しません。しかし、それらは標準的な観点から表現の意味に影響を及ぼします。これは単純にid式(または名前)ではありません。 – StoryTeller

答えて

0

第1に、コピーアンドムーブコンストラクタには副作用(IOを実行する)があるため、「仮」ルールはここでは適用されません。したがって、GCCは、その見出しのもとでコピー/移動を逃すことはできません。

一見したところ、私はelisionを許可する言葉を見ることができないので、GCCのバグだと思う。一方、私はコピー/ムーブ・エリシジョンの範囲を広げて、このケースを含めることを標準としたい。 (あなたが提示した最小限の例では、どのように問題が発生するのかわかりません - 私は、あなたがどこに大きな例があるのか​​推測しています)。

+0

コンパイラは、この場合副作用があっても、コピー/移動を削除することができます。 – Zereges

+0

@Zeregesコピー/移動エリートが許可されている場合、コンパイラが(標準で定義されている正式な意味で)*副作用を持っていても許されます。私の最初の段落のポイントは、コンストラクタが副作用を持たない場合、12.8/31の下でelisionが許可されていなくても、それらを省略することができるということです。 12.8/31は "この場合"には適用されませんが、 "この場合"には "as-if"は適用されません=> elisionはバグです。 –

+0

@Zereges上記のコメントの一部を含めるには、私の答えを拡大する必要がありますか? –

関連する問題