web-dev-qa-db-ja.com

文字列定数から 'char *'への変換はCでは有効ですが、C ++では無効なのはなぜですか

C++ 11標準(ISO/IEC 14882:2011)は§ C.1.1で次のように述べています:

char* p = "abc"; // valid in C, invalid in C++

C++では、文字列リテラルへのポインタを変更しようとするとクラッシュするため、文字列リテラルへのポインタは有害であるため問題ありません。しかし、なぜCで有効なのでしょうか?

C++ 11には次のようにも書かれています。

char* p = (char*)"abc"; // OK: cast added

つまり、最初のステートメントにキャストが追加された場合、キャストは有効になります。

キャストにより、C++で2番目のステートメントが有効になるのはなぜですか?最初のステートメントとはどう違うのですか?まだ有害ではありませんか?もしそうなら、なぜ規格はそれがOKだと言ったのですか?

122
rullof

C++ 03までは、最初の例は有効でしたが、非推奨の暗黙的な変換を使用しました。文字列リテラルは、その内容を変更できないため(未定義の動作を引き起こすことなく)、タイプchar const *として扱う必要があります。

C++ 11の時点で、非推奨であった暗黙の変換は公式に削除されたため、それに依存するコード(最初の例のように)はコンパイルできなくなります。

コードのコンパイルを許可する1つの方法に注目しました。暗黙の変換は削除されましたが、explicit変換は引き続き機能するため、キャストを追加できます。 notですが、これはコードの「修正」を検討します。

本当にコードを修正するには、ポインターのタイプを正しいタイプに変更する必要があります。

char const *p = "abc"; // valid and safe in either C or C++.

それがC++で許可されている(そしてまだCである)理由について:その暗黙的な変換に依存する既存のコードがたくさんあり、そのコードを壊す(少なくとも公式の警告なしで)ように見えるように標準委員会に悪い考え。

144
Jerry Coffin

歴史的な理由でCで有効です。 Cは伝統的に、文字列リテラルの型はchar *ではなくconst char *であると指定していましたが、実際に変更することは許可されていないと言って修飾しました。

キャストを使用する場合、基本的には、デフォルトの型一致ルールよりもよく知っていることをコンパイラーに伝えているため、割り当てが正常に行われます。

10
Barmar