誰の助けを借りてconst_cast
も、宣言された定数オブジェクトを変更できるため、const
修飾子は何に使用されますか?
const
とにかく、彼が宣言したものが変更されないことを誰かがどのように保証できるのでしょうか?
その通りです。多くの場合、 の使用はconst_cast
設計上の欠陥、または制御できない API を示しています。
ただし、例外があり、オーバーロードされた関数のコンテキストで役立ちます。本C++ Primerから例を引用しています。
// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string &s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
この関数は、 への参照を受け取って返しますconst string
。非 conststring
引数のペアで関数を呼び出すことができますがconst string
、結果として a への参照を取得します。shorterString
const 以外の引数を指定すると、単純な参照が生成されるバージョンが必要になる場合があります。を使用して、このバージョンの関数を記述できますconst_cast
。
string &shorterString(string &s1, string &s2)
{
auto &r = shorterString(const_cast<const string&>(s1),
const_cast<const string&>(s2));
return const_cast<string&>(r);
}
shorterString
このバージョンは、引数を への参照にキャストすることにより、 の const バージョンを呼び出しますconst
。const string
その関数は、元の非 const 引数の 1 つにバインドされていることがわかっているa への参照を返します。したがって、リターンでその文字列をプレーンにキャストしても安全であることがわかっていますstring&
。
const_cast
const
もともと非 const 変数に追加する場合にのみ安全です。const
元々 const であったオブジェクトからステータスを削除してから書き込み操作を実行しようとすると、未定義の動作が発生します。
この質問は関連しています。
また、msdnページには次のように書かれています(強調は私のものです):
任意のオブジェクト型へのポインターまたはデータ メンバーへのポインターは、const、volatile、および __unaligned 修飾子を除いて同一の型に明示的に変換できます。ポインターと参照の場合、結果は元のオブジェクトを参照します。データ メンバーへのポインターの場合、結果はデータ メンバーへの元の (キャストされていない) ポインターと同じメンバーを参照します。参照されるオブジェクトの型によっては、結果のポインター、参照、またはデータ メンバーへのポインターを介した書き込み操作によって、未定義の動作が発生する場合があります。const_cast 演算子を使用して、定数変数の定数ステータスを直接オーバーライドすることはできません。
定数オブジェクトの有無にかかわらず、誰も変更できませconst_cast
ん。const_cast
定数オブジェクトを変更することはできません。
constness を削除する場合、 の目的は、非定数オブジェクトにつながるアクセス パスconst_cast
(ポインターまたは参照)から constness を削除できるようにすることです。
例えば
int i = 5;
const int *p = &i;
*const_cast<int *>(p) = 10;
assert(i == 10);
上記のコードでは、ポインタを介しconst_cast
てオブジェクトへの変更アクセスを取得するために使用されています。オブジェクト自体は定数ではないため、その変更に問題はありません。i
p
i
それがの目的ですconst_cast
。逆の目的にも使用できます。つまり、ポインターまたは参照型に constness を追加します。しかし、「定数オブジェクトの変更」は でできることではありませんconst_cast
。定数オブジェクトは変更できません。
const_cast
constness をキャストするための 1 つの可能な用途は、const
引数を使用しないが引数を変更しない、またはローカル コピーのみを変更する C 関数を呼び出すことです。
パーツをキャストしてからconst
データを変更すると、ほとんどの場合、未定義の動作が発生します。