696 名前:デフォルトの名無しさん[sage] 投稿日:2010/03/09(火) 07:26:55
通らない
ttp://codepad.org/d4Wo3ozT
int main()
{
int ** pp = nullptr ;
int * const * const pcpc = pp ; // これはコンパイルが通る。
int const ** cpp = pp ;// エラー。なんで?
}
これは、規格の4.4 Qualification conversions [conv.qual]によって、明示的に禁止されている。何故か。これを許可してしまうと、C++の型システムのconst性に、穴が生じるのだ。
int main()
{
// i は書き換えられない。
int const i = 0 ;
int * p ;
// もちろんこれはエラー
p = &i ;
int const ** cpp = &p ; // もし、これが許可されているとする。
// *cppは、pである。pはiへのポインタを持つようになる。
*cpp = &i;
// pはiを参照しているので、pを経由して、constであるはずのiを書き換えられる。
*p = 123 ;
}
つまり、この標準変換を認めてしまうと、暗黙のうちに、const性を破ることができてしまうのだ。
もし、何らかの理由で、どうしても、このような型変換を行いたい場合は、const_castをするしかない。
int ** pp = nullptr ; int const ** cpp = const_cast<int const **>(pp) ;// OK。ただし自己責任。
ちなみに、const性を破らないことが保証できれば、キャストはできる。つまり、以下のようなことはできる。
int ** pp = nullptr ; int const * const * cpcp = pp ; int i = 0 ; // エラー *cpcp = &i ;
なぜなら、*cpcpの型は、int const * constなので、参照先のポインタを変更することはできないからだ。これによってconst性は守られるので、暗黙なキャストも許可されている。
2 comments:
何か現行の標準C++にも似たような事があったような無かったような
その場合の動作は未定義 undefined とされていました
つまり鼻から悪魔ですね
この部分は、C++98の頃から変わっていないはずですが。
Post a Comment