1

デバッグセッションの後、次のサンプルコードが警告なしでコンパイルされることに気付きました(g ++-4.7.2 -Wextraおよび-Wall)

char *p;
char *q = std::move(p);
*p = 'p';
*q = 'q';

私は少しショックを受けました、そして私はそれについて3つの質問があります。

1-移動セマンティクスについて何かが欠けていて、この状況で警告を発行しない理由がありますか、それともgccのチェックが十分ではありませんか?

2-次のコードは警告をスローする必要がありますか?

char c = 'c';
char *p = &c;
char *q = std::move(p);
*p = 'p';

私が理解している限り、afterstd::move(p) pは任意の値を保持できるため、一度p移動すると、初期化されていない変数のようになります。

3-他のツール/コンパイラはこれらのエラーをチェックできますか?

4

2 に答える 2

1

1- 移動のセマンティクスについて何かが欠けています。この状況で警告がスローされないのには理由がありますか、それとも gcc チェックが十分ではありませんか?

コードが間違っているため、警告が表示されます。G++ は への呼び出しを「見抜く」ほどスマートではありませんstd::move。関数への参照によって初期化されていない変数を渡すことは有効であるため (その関数は変数を初期化する可能性があります)、std::moveそれ自体を呼び出しても警告はトリガーされません。に値が割り当てられるためq、コンパイラに対して初期化されているように見えます。

G++ が呼び出しをインライン化するように最適化をオンにするとstd::move、G++ 4.7 からエラーが発生します。

f.cc: In function ‘int main()’:
f.cc:6:9: warning: ‘p’ is used uninitialized in this function [-Wuninitialized]

これは、への呼び出しがstd::moveコンパイラにとって「不透明」ではなくなったためです。インライン化されたコードを分析するとp、値が割り当てられないことがわかります。qコンパイラは、決して適切な値が得られないことを確認できるほど賢くありません。内部のキャストstd::moveがコンパイラを混乱させる可能性があります。

2- 次のコードは警告をスローする必要がありますか?

No.std::moveはポインタなどの基本的な型を変更しないため、 の値はp変更されません。標準ライブラリは、オブジェクトが移動された後、「有効だが未指定」の状態のままであると述べています。これは、標準では一般に移動コンストラクターまたは移動代入演算子の正確な動作が定義されていないためintですchar*。移動コンストラクターはありません。std::move(p)オブジェクトを右辺値にキャストするだけで、オブジェクトは変更されqず、値で初期化しても変更されません-値をコピーするだけです。

3- 他のツール/コンパイラでこれらのエラーをチェックできますか?

最適化をオンにしても、Clang と ICC は最初の例について警告しません。

警告は非常に便利ですが、コンパイラは完全ではなく、すべての安全でないコードについて警告することは不可能であることに注意してください。安全でないコードに対して警告が表示されなくても (コンパイラにバグ レポートを開いて改善を要求するなど)、まったく驚かないでください。それは、コードに問題がないことを意味するものではありません。警告がないからといって、バグがないわけではありません。

于 2013-01-19T22:40:00.270 に答える
0

つまり、ポインターのコピー コンストラクターと同じで、値をコピーします。したがって、C++11 に関する限り、これはポインターをコピーします。最初のケースでは、初期化されていないポインターをコピーしています。

これらがstd::unique_ptrオブジェクトである場合、それは正しいコードではありません。しかし、コンパイラがそれについて警告することを期待する理由はありません。なぜなら、移動元のオブジェクトがそれを呼び出していないことをコンパイラが確信する方法がないからです。operator*

一般に、標準ライブラリは、移動元のオブジェクトは有効だが未定義の状態のままであると述べています。たとえば、これは完全に合法です。

std::vector<int> src = ...;
std::vector<int> dest = std::move(src);
src.assign(...);

std::unique_ptr移動元のオブジェクトがどのような状態のままであるかを正確に指定するという点で異なります。ただし、コンパイラは、どの型についてもそれを想定できません。オブジェクトが、特定の関数呼び出しが失敗しなければならない無効な状態のままであると想定することはできません。

于 2013-01-19T22:42:44.757 に答える