6

C++ には、配列への読み取り専用アクセスのみを必要とする関数がありますが、const 以外のポインターを受け取ると誤って宣言されています。

size_t countZeroes( int* array, size_t count )
{
    size_t result = 0;        
    for( size_t i = 0; i < count; i++ ) {
       if( array[i] == 0 ) {
           ++result;
       }
    }
    return result;
}

const 配列に対してそれを呼び出す必要があります。

static const int Array[] = { 10, 20, 0, 2};

countZeroes( const_cast<int*>( Array ), sizeof( Array ) / sizeof( Array[0] ) );

これは未定義の動作になりますか?もしそうなら - プログラムはいつUBに実行されますか - const_castを実行して関数を呼び出すとき、または配列にアクセスするときは?

4

5 に答える 5

14

はい、許可されています (危険な場合!)。未定義の動作を引き起こすのは、キャスト自体ではなく、オブジェクトへの実際の書き込みconstです (7.1.5.1/4 [dcl.type.cv])。

5.2.11/7 [expr.const.cast] の標準的な注記のように、オブジェクトの型によっては、キャスト アウェイの結果であるポインターを介して書き込もうとすると、const未定義の動作が発生する可能性があります。

于 2009-10-09T07:15:34.690 に答える
1

あなたのコードは配列を変更せず、 を使用して何をしているのかをコンパイラに伝えたので、const_cast実際には問題ありません。ただし、技術的には未定義の動作を呼び出していると思います。関数宣言を修正するか、その const-safe バージョンを記述、宣言、および使用するのが最善です。

于 2009-10-09T07:02:51.227 に答える
1

はい、できます。いいえ、関数が本当に配列に書き込もうとしない限り、未定義の動作ではありません。

于 2009-10-09T18:22:20.200 に答える
1

の問題const_castは常に同じです。キャストとキャストのように、「ルールを破る」ことvoid*ができます。確かにそれは可能ですが、問題は、なぜそうすべきかということです。

この場合はもちろん問題ありませんが、なぜsize_t countZeroes( const int* array, size_t count )最初に宣言しなかったのかを自問する必要があります。

そして、一般的なルールとしてconst_cast

  1. 見つけにくいバグが発生する可能性があります
  2. あなたはコンパイラとの定数合意を捨てています
  3. 基本的に、言語を低レベルのものに変えています。
于 2009-12-19T01:51:47.260 に答える
-2

const_cast最初に UB として定義されたオブジェクトを使用するconstと、 を呼び出した時点で未定義の動作がすぐに発生しますconst_cast

于 2009-10-09T07:02:26.097 に答える