質問
あまり情報が見つかりません const_cast
. 。(Stack Overflow で) 私が見つけることができた唯一の情報は次のとおりです。
の
const_cast<>()
変数の const(ness) (または volatile-ness) を追加/削除するために使用されます。
これでは緊張してしまいます。を使用できますか const_cast
予期せぬ動作を引き起こしますか?もしそうなら、何ですか?
また、いつ使用しても問題ありませんか const_cast
?
解決
const_cast
もともと安全ではなかった変数をキャストしている場合にのみ安全です。const
. 。たとえば、パラメータを受け取る関数がある場合、 const char *
, 、そして、変更可能なものを渡します char *
, 、安全です const_cast
そのパラメータを元に戻す char *
そしてそれを修正します。ただし、元の変数が実際に const
, 、次に使用します const_cast
未定義の動作が発生します。
void func(const char *param, size_t sz, bool modify)
{
if(modify)
strncpy(const_cast<char *>(param), sz, "new string");
printf("param: %s\n", param);
}
...
char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true); // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true); // UNDEFINED BEHAVIOR
他のヒント
const_cast が安全で便利な状況は 2 つ考えられます (他にも有効な場合があるかもしれません)。
1 つは、const インスタンス、参照、またはポインターがあり、const が正しくない API にポインターまたは参照を渡したいが、確実にオブジェクトを変更しない場合です。実際には何も変わらないことを信頼して、ポインターを const_cast して API に渡すことができます。例えば:
void log(char* text); // Won't change text -- just const-incorrect
void my_func(const std::string& message)
{
log(const_cast<char*>(&message.c_str()));
}
もう 1 つは、「mutable」を実装していない古いコンパイラを使用していて、論理的には const であるがビット単位の const ではないクラスを作成したい場合です。const メソッド内で 'this' を const_cast し、クラスのメンバーを変更できます。
class MyClass
{
char cached_data[10000]; // should be mutable
bool cache_dirty; // should also be mutable
public:
char getData(int index) const
{
if (cache_dirty)
{
MyClass* thisptr = const_cast<MyClass*>(this);
update_cache(thisptr->cached_data);
}
return cached_data[index];
}
};
それが信じられないのですが、 のみ const_cast について見つけることができる情報。からの引用 Google で 2 回目のヒット:
constとして明示的に宣言されたオブジェクトのconstnessをキャストし、それを変更しようとすると、結果は未定義です。
ただし、constとして明示的に宣言されていないオブジェクトのconstnessを捨てると、安全に変更できます。
アダムの言うこと。const_cast が役に立つ別の例:
struct sample {
T& getT() {
return const_cast<T&>(static_cast<const sample*>(this)->getT());
}
const T& getT() const {
/* possibly much code here */
return t;
}
T t;
};
まず型に const を追加します this
を指す場合、その const バージョンを呼び出します getT
, 次に、戻り値の型から const を削除します。これは有効です。 t
非定数でなければなりません (それ以外の場合は、 getT
電話はできなかったでしょう)。これは、関数本体が大きく、冗長なコードを避けたい場合に非常に役立ちます。
簡単に言うと「いいえ、安全ではありません」です。
長い答えは、それを使用するのに十分な知識があれば安全であるはずだということです。
あなたがキャストしているとき、あなたが本質的に言っているのは、「私はコンパイラーが知らないことを知っている」ということです。 const_castの場合、あなたが言っているのは、「この方法では、コンクロッドのリファレンスまたはポインターを取り入れていても、パラメーターを渡すことはないことを知っています。」
したがって、キャストを使用する際に自分が知っていると主張していることを実際に知っているのであれば、それを使用しても問題ありません。
コンパイラが const と判断したものを変更し始めると、スレッド セーフの可能性が台無しになります。
#include <iostream>
using namespace std;
void f(int* p) {
cout << *p << endl;
}
int main(void) {
const int a = 10;
const int* b = &a;
// Function f() expects int*, not const int*
// f(b);
int* c = const_cast<int*>(b);
f(c);
// Lvalue is const
// *b = 20;
// Undefined behavior
// *c = 30;
int a1 = 40;
const int* b1 = &a1;
int* c1 = const_cast<int*>(b1);
// Integer a1, the object referred to by c1, has
// not been declared const
*c1 = 50;
return 0;
}