2009-10-09 13 views
5

++私は唯一の配列への読み取り専用アクセスが必要ですが、誤って非constポインタを受け取るように宣言された関数があります。constオブジェクトへの読み取り専用アクセスのためにconst_castを使用していますか? Cでは

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をやってfunctonを呼び出すときや配列にアクセスするときは?

+0

は、私はあなたが関数の宣言を変更することはできませんと仮定...しかし、私は強く、より良いものにラッパーを書いて、その中に汚い仕事をするためにあなたを促します。 –

+0

たぶん、まったく別のものを試してください: 'size_tのnumZeros =のstd ::回数(配列、配列+はsizeof(配列)/はsizeof(配列[0])、0);' – MP24

+0

MP24 @この関数は、だけの簡単な図であります問題。 – sharptooth

答えて

13

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

5.2.11/7 [expr.const.cast]の標準注意事項として、オブジェクトのタイプによっては、constをキャストした結果であるポインタを介して書き込むと、未定義の動作が発生することがあります。

-2

最初にconstと定義されているオブジェクトにconst_castを使用すると、未定義の動作はconst_castと呼ばれる時点で直ちに発生します。

+3

いいえ、UBはconstオブジェクトへの書き込みの瞬間にあり、constを削除しません。 –

+0

ああ、申し訳ありませんが、私はinterwebsのいくつかの相反するアドバイスを持っています –

+3

これらのWebは難しいことができます。 – GManNickG

1

あなたのコードは、配列を変更しないと、あなたは、あなたがconst_castを使って何をしているか知っているコンパイラを語っているので、あなたが実際にOKになります。しかし、私はあなたが技術的に未定義の振る舞いをしていると信じています。関数の宣言を固定したり、const-safe版を宣言して使用したりするのが最適です。 (危険な場合!)

+0

"有効なC++"または "より効果的なC++"でconstを使用する方法をお読みください。これはconst_castのいくつかの有効な使い方を示しています(例えば、コードの重複を避けるため)。 –

+0

-1これは未定義の動作ではないため-1です。歴史的には、C++ 98のコードは、標準Cとの相互運用が難しくなりました。しかし、私はアドバイスについて完全にあなたと話しています。 –

1

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

1

const_castの問題は常に同じです。それはあなたがキャストするように、そして "012"を行うことができるのと同じように、 "ルールを破る"ことができます。

この場合には、もちろん大丈夫ですが、あなたはなぜあなたが最初の場所でsize_t countZeroes(const int* array, size_t count)を宣言していない自分自身に尋ねるべき?

として

一般的なルールについて const_cast

  1. それはあなたが言語を回している
  2. 基本的にコンパイラでのconst-契約を捨てている
  3. バグを見つけるのは難しい生じることが下位のものに変換する。
関連する問題