答えは、コンパイルするC ++標準によって異なります。次の行を除いて、すべてのコードはすべての標準で完全に整形式です‡。
char * s = "My String";
現在、文字列リテラルには型がconst char[10]
あり、それへの非constポインターを初期化しようとしています。char
文字列リテラルのファミリー以外のすべてのタイプでは、そのような初期化は常に違法でした。例えば:
const int arr[] = {1};
int *p = arr; // nope!
ただし、C ++ 11より前では、文字列リテラルの場合、§4.2/ 2に例外がありました。
ワイド文字列リテラルではない文字列リテラル(2.13.4)は、タイプ " pointer to char "の右辺値に変換できます。[...]。どちらの場合も、結果は配列の最初の要素へのポインターです。この変換は、明示的な適切なポインターターゲットタイプがある場合にのみ考慮され、左辺値から右辺値への変換が一般的に必要な場合は考慮されません。[注:この変換は非推奨です。付録Dを参照してください。]
したがって、C ++ 03では、コードは完全に問題なく(非推奨ですが)、明確で予測可能な動作を持っています。
C ++ 11では、そのブロックは存在しません-に変換された文字列リテラルにそのような例外はありません。そのchar*
ため、コードは、int*
先ほど提供例と同じように。コンパイラーは診断を発行する義務があります。理想的には、C ++型システムの明らかな違反であるこのような場合、理想的なコンパイラーはこの点(たとえば、警告を発行すること)だけでなく、失敗することを期待します。あからさま。
コードは、理想的にはコンパイルしないでください。ただし、gccとclangの両方で実行します(このタイプのシステムホールが10年以上廃止されているにもかかわらず、おそらく多くのコードが壊れているため、ほとんど利益が得られないためです)。コードの形式が正しくないため、コードの動作がどうなるかを推論しても意味がありません。しかし、この特定のケースとそれが以前に許可されていた歴史を考えると、結果のコードを暗黙的const_cast
なものであるかのように解釈するのは不当なストレッチとは思えません。
const int arr[] = {1};
int *p = const_cast<int*>(arr); // OK, technically
これで、実際には二度と触れないので、プログラムの残りの部分は完全にうまくいきますs
。読書作成されたconst
オブジェクトをconst
ポインタ以外で、まったく問題ありません。そのようなポインタを介してcreated- objectを書き込むことconst
は未定義の動作です:
std::cout << *p; // fine, prints 1
*p = 5; // will compile, but undefined behavior, which
// certainly qualifies as "unpredictable"
s
コードのどこにも変更がないため、プログラムはC ++ 03では問題なく、C ++ 11でのコンパイルに失敗するはずですが、とにかく実行されます-コンパイラーが許可する場合、未定義の動作はまだありません† 。コンパイラがC ++ 03ルールを[誤って]解釈していることを考慮して、「予測できない」動作につながるようなものは何もありません。でも書いてs
、すべての賭けはオフです。C ++ 03とC ++ 11の両方。
† ただし、不適切な形式のコードは当然のことながら、妥当な動作を期待
できません。ただし、そうでない場合を除き、Matt McNabbの回答を参照してください