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