19

この件についての私の理解と結論を確認したいと思います。


IRCでは、次のように質問されました。

一時オブジェクトにバインドされてconst_castいる参照に受け入れられますか?const

翻訳:const彼は一時的なものにバインドされたref-to-constを持っており、それを変更するためにその性質を捨てたいと思っています。

私の回答は、以前に同様の質問をしたことでした。そこでは、一時的なもの自体は本質的にではないため、参照の性質をconst捨てconstて、結果を通じてそれらを変更できるというコンセンサスが得られたようです。 。そして、その元のref-to-がまだ存在している限りconst、これは一時的なものの存続期間に影響を与えません。

あれは:

int main()
{
   const int& x = int(3);

   int& y = const_cast<int&>(x);
   y = 4;

   cout << x;
}
// Output: 4
// ^ Legal and safe

私は正しいですか?


(もちろん、そのようなコードが実際に推奨されるかどうかはまったく別の問題です!)

4

2 に答える 2

9

いいえ。

まず、私が知る限り、それが文字通りであるかどうかは関係ありません。非クラス型の右辺値には常に非cv修飾型(§3.10/ 9)がありますが、§8.5.3(参照の初期化)では次のようになります。

タイプ「cv1T1」への参照は、タイプ「cv2T2」の式によって次のように初期化されます。

[...]

-

それ以外の場合は、タイプ「cv1 T1」の一時オブジェクトが作成され、非参照コピー初期化(8.5)のルールを使用して初期化式から初期化されます。次に、参照は一時的なものにバインドされます。T1がT2に参照関連している場合、cv1はcv2と同じcv-qualification、またはcv2よりも大きいcvqualificationである必要があります。そうしないと、プログラムの形式が正しくありません。

(上記のすべてのポイントは、左辺値またはクラスタイプのいずれかに関係します。)

私たちの場合、次のようになります。

int const& x = ...;

したがって、 cv1 T1int constであり、作成する一時オブジェクトのタイプは int constです。これは(オブジェクト上の)トップレベルの定数であるため、これを変更しようとすると未定義の動作になります。

少なくとも、それは私の解釈です。基準がこれについてもう少し明確になったらいいのにと思います。

于 2011-11-23T17:41:29.447 に答える
1

答えは、一時的なものがどのように作成され、参照がどのように初期化されるかによって異なります。

一時を非const型のオブジェクトとして明示的に作成し、const-referenceが作成した一時に特別にアタッチされることが保証されている場合は、参照のconstnessを安全にキャストして、オブジェクトを変更できます。

一方、一時がコンパイラによって暗黙的に作成された場合、一時自体はconstになります。その場合、その一時的な変更はUBにつながります。

残念ながら、C ++言語標準自体は、最初の初期化アプローチが必然的に採用される状況を保証していないようです。どのような状況でも、コンパイラーは元の一時的なものの追加の一時的なコピーを導入することができます。新しい一時的なものは(上記のように)constであるため、変更できません。これが発生するかどうかは、8.5.3 / 5で説明されているように、実装によって定義されます。

したがって、一般的な場合、答えはノーですが、実装固有の答えは異なる場合があります。

于 2011-11-23T18:25:47.643 に答える