_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-correctではないAPIにポインターまたは参照を渡したいが、CERTAINがオブジェクトを変更しない場合です。ポインターを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について見つけることができるonly情報だとは信じ難い。 2番目のGoogleヒット からの引用:
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;
};
最初にthis
が指す型にconstを追加し、次にgetT
のconstバージョンを呼び出し、戻り型からconstを削除します。これは、t
非constでなければなりません(そうでなければ、getT
の非constバージョンを呼び出すことはできませんでした)。これは、関数本体が大きく、冗長なコードを避けたい場合に非常に役立ちます。
短い答えはノーです、それは安全ではありません。
長い答えは、あなたがそれを使用するのに十分知っているなら、それは安全でなければならないということです。
あなたがキャストしているとき、あなたが本質的に言っているのは、「コンパイラが知らないことを知っている」ということです。 const_castの場合、あなたが言っているのは、「このメソッドは非const参照またはポインターを受け取りますが、渡すパラメーターを変更しないことはわかっています。」
そのため、キャストを使用して知っていると主張していることを実際に知っている場合は、キャストを使用しても問題ありません。
コンパイラがconstであると考えていたものを変更し始めると、スレッドの安全性が失われる可能性があります。