2

以下のものはどこにも使用していませんが、それでもこの質問は長い間私の頭の中にありました。

void* operator new (size_t size)
{
  // distort `size` to other value
  return malloc(size);
}

上記がオーバーロードの明確に定義された動作ではない可能性があることを知っているのでnew(たとえば、sizeが減少した場合)、なぜ標準でコンパイラにそれを強制しないのvoid* operator new (const size_t);ですか?

同じことがoperator delete、必要な場所でも議論できます(ポインタが変更されないようにvoid operator delete (void* const);追加します)。const

4

5 に答える 5

8
void* operator new (const size_t n);
void* operator new (size_t n);

これら2つは、の完全に同一の宣言ですoperator new。唯一の違いは、それが定義である場合、nは関数本体内で変更できるかどうかです(パラメーターは値によって渡されるため、呼び出し元には関係ありません)。これは実装の詳細であるため、標準ではそれについては説明されていません。

最上位のconstは関数宣言では無視されることを忘れないでください。それらは定義にのみ関連します。

于 2011-07-22T11:20:34.800 に答える
6

どちらの場合も引数のタイプであり、const std::size_tプレーンstd::size_tstd::size_tです。この標準では、宣言で関数シグニチャを処理するときに(後で定義で)、const型から削除されるように規定されています。特定の段落は§8.3.5/3にあります:

[...]パラメータタイプのリストを作成した後、関数タイプを決定するために、これらのタイプに対していくつかの変換が行われます。パラメータタイプを変更するcv修飾子はすべて削除されます。[例:タイプvoid()(const int)はvoid()(int)になります—例を終了します]

さて、関数の定義では、はconstあなたが提案する効果を持っています:あなたが引数を変更するのをブロックします。引数operator newを使用して自由に実装できます。const std::size_t一方で、それを強制することは基本的に役に立たないでしょう。他の人が述べたように、引数がconstであるという事実は、それを別の変数にコピーしてその変数を使用することによって覆すことができます。言語に真の価値を追加しない場合、コンパイラーに検証の余分な負担を追加しても意味がありません。

于 2011-07-22T13:02:33.523 に答える
2

非参照引数の定数は、ほんのわずかな重要性しかありません。

規格は、発信者の観点から「重要な」ことを定義しています。

これらの値による引数の恒常性は、それらを使用するコードを変更せず、変更することもできません。実装者は自分の面倒を見ることができます。

更新:必要に応じて、このように書くことができます。

int f (const int);
int f (int) {return 0;}

int main () {
    int i;
    f (i);
}

上記でエラーは発生しませんでした。先に進み、size_tを構成します:-)

反対意見を予測するには:ここでfoperator new代役などを使用します。したがって、矛盾する宣言/定義がありますが、コンパイラは文句を言いません。なんで?それは問題ではないからです。

于 2011-07-22T11:14:38.693 に答える
2

さて、それがそうであるふりをしましょうconst

void* operator new (const size_t size)
{
   size_t alteredSize = size;
   alteredSize += 10; // for whatever reason
   return malloc( alteredSize );
}

これは完全に同じです

void* operator new (size_t size)
{
   size += 10;
   return malloc( size );
}

const関数にコピーされた(値によって渡された)パラメーターでは、その値の使用は強制されません-関数は書き込み可能なコピーを作成し、そのコピーを変更できます。

于 2011-07-22T11:16:49.553 に答える
1

あなたはすでに多くの良い答えを受け取っていますoperator new。constの引数を作成しないためのもう1つの引数:オーバーライドする実装では、Cookieやガードワードなど、要求されたよりも多くのスペースを割り当てたい場合があります。sizeoperator new

演算子の削除についても同じことが言えます。演算子の削除を無効にする必要があります(void * const); (ポインターが変更されないようにconstを追加します)。

仮想メモリを使用する最新のオペレーティングシステムのほとんどでfreeは、割り当てられたメモリをOSに解放する必要はありません。そのメモリはまだプログラムの仮想空間にある可能性があります。ペダンティックオーバーライドは、ポイントされたメモリを削除する前に絶対ガベージで埋めて、呼び出し元の関数によるそのメモリのその後の使用をさらに無効にすることをお勧めします。呼び出し元の関数は、ポイントされたメモリを削除した後にそれを使用してはなりません。それでは、なぜoperator delete不要な制限でホブリングするのでしょうか。

于 2011-07-22T13:32:22.207 に答える