3

Microsoft Developer Network http://msdn.microsoft.com/en-us/library/dd162487(v=VS.85).aspxからコピーしたコードを次に示します。

LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{

**PAINTSTRUCT ps;  
HDC hdc;**

switch (message) 
{ 
    case WM_PAINT: 
        hdc = BeginPaint(hwnd, &ps); 
        TextOut(hdc, 0, 0, "Hello, Windows!", 15);
        EndPaint(hwnd, &ps); 
        return 0L; 

    // Process other messages.   
} 
} 

私はおそらく間違っていますが、コンパイラーが次のいずれかのようなステートメントを実行するたびに、私は思っていました。

int var1  
double var2  
char var3[]  
PAINTSTRUCT ps  
HDC hdc  

コンピューターは新しい変数を作成します。少なくとも、新しい変数を作成したいときにそれを書くので、それは考えるのが論理的なことですよね?

また、次のようなコードブロックがあるといつも思っていました。

for(int i = 0; i < 100; i++)
    int sum = i;

コンピュータは 100 の異なる変数をすべて同じ名前で作成し、変数sumに含まれる何らかの値を作成します。i

上記のサンプル コードでは、関数 WndProc がプログラムの過程で何度も呼び出されますが、関数が作成する "ps" と "hdc" という 2 つの変数は、関数が実行されるときにのみ使用されます。 .

では、コンピューターは決して使用しない余分な PAINTSTRUCT 変数と HDC 変数を個別に大量に作成するのでしょうか?
case WM_PAINT: の後に "ps" と "hdc" を宣言すると、少なくとも少しは効率的ではないでしょうか?

case WM_PAINT:
{ 
     **PAINTSTRUCT ps;  
     HDC hdc;**

     hdc = BeginPaint(hwnd, &ps); 
     TextOut(hdc, 0, 0, "Hello, Windows!", 15);
     EndPaint(hwnd, &ps); 
 }
 return 0L; 
4

5 に答える 5

2

私はおそらく間違っていますが、コンパイラーがこれらのいずれかのようなステートメントを実行するたびに、私は思っていました:

int var1  
double var2  
char var3[]  
PAINTSTRUCT ps  
HDC hdc  

コンピューターは新しい変数を作成します。

これらの変数は、実行時のストレージ スペースに対応します。それらはローカルであるため、スタック上に存在する可能性が高く、これらのローカルにスペースを割り当てることは、スタック ポインターを移動するのと同じくらい簡単です。これは猛烈に速いです。

また、次のようなコード ブロックがあると常に考えていました。 for(int i = 0; i < 100; i++) int sum = i;

コンピューターは、すべて同じ名前「sum」と「i」に含まれる値を持つ 100 の異なる変数を作成します。

ここで発生する可能性が高いのは、ループの反復ごとにスタック上の同じ場所が再利用されることです。

case WM_PAINT: の後に "ps" と "hdc" を宣言すると、少なくとも少しは効率的ではないでしょうか?

いいえ、それらはローカルであり、スタックに割り当てられる可能性が高く、コード内で宣言する場所に関係なく、メソッドが入力されるとすぐにスペースが予約されます。

最後に、ここでパフォーマンスについて心配することは、せいぜいマイクロ最適化です。コードの意味に注目してください。コンパイラーに可能な限り効率的に実行可能コードに変換させます。顧客が期待するパフォーマンス要件を満たさないパフォーマンスの問題がある場合にのみ、心配する必要があります。

于 2011-04-23T21:11:22.450 に答える
1

コンピューターが多くのローカル変数を宣言することは間違いありませんが、幸いなことに、これは非常に効率的です。コンパイラは通常、関数が最初に呼び出されるときにローカル変数を生成するコードを単一のアセンブリ命令として出力するため、これらの変数を作成するオーバーヘッドは無視できます。ループの例では、コンパイラは通常、変数を複数回作成および破棄しません。むしろ、一度作成すると、ループの各反復でスペースが再利用されます。つまり、変数は各反復で論理的に作成および破棄されますが、生成されたコードでは、実際には複数の反復で共有されます。

一般的な規則として、パフォーマンスが本来あるべき水準を下回っていると信じる特別な理由がない限り、プログラムの効率について心配する必要はありません。プログラムを実際に実行しないと、最適化がプログラムの実行時間に有益な影響を与えるかどうかを知るのは非常に難しいため、最初から最適化されたコードではなく、クリーンでエレガントなコードを書くことを優先する必要があります。通常、プロファイラーを使用してコードのどの部分が遅いかを判断し、そこに最適化の取り組みを集中させます。

于 2011-04-23T21:09:14.137 に答える
1

プリミティブ ローカル変数 (ポインター、int、double、float など) およびプリミティブの配列の場合、変数を宣言すると実際にその変数にスペースが "割り当て" られますが、実際に行われるのはコンパイラが "I'm goingスタック上のこのスポットを呼び出すには、スタック ポインターの 3 ワード下、i ." 実際の計算は行われません。命令はまったく実行されません! したがって、ループの内側または外側で「合計」を宣言しても、まったく違いはありません。

ただし、ローカルで宣言されたクラス インスタンスの場合は異なります。オブジェクトを宣言すると、ブロックに入ったときにコンストラクターが呼び出され、ブロックから出たときにデストラクタが呼び出され、命令が実行されます。そのため、注意が必要です。

于 2011-04-23T21:10:39.533 に答える
1

コンピュータは新しい変数を作成します

これは表面的にのみ真実です。技術的には、プロセッサが実際に行うことは、スタック ポインタを特定の長さに移動することです。宣言する変数にコンストラクターがない場合、このアクションのオーバーヘッドは事実上ゼロです。

それでは、コンピューターは決して使用しない多くの別個の追加の PAINTSTRUCT 変数と HDC 変数を作成するのでしょうか?

いいえ、これは正しくありません。関数が返されると、これらの変数に割り当てられたすべてのスタック スペースが再利用され、何も無駄になりません。

case WM_PAINT: の後に "ps" と "hdc" を宣言すると、少なくとも少しは効率的ではないでしょうか?

ありそうもない。コンパイラは、宣言をどこに置いても、これらの変数の宣言と割り当てられたスペースをスタックに表示する可能性があります。繰り返しますが、変数にコンストラクターがない限り、これは当てはまります。そうであれば、それらをケースに入れると、コンストラクターの呼び出しが節約されます。

于 2011-04-23T21:12:56.303 に答える
0

コンパイラは、結果が同じである限り、コードに大幅な変更を加えます。特にリリース (非デバッグ) ビルドでは。

これは、未使用のコードがある場合、変数の宣言が早すぎる場合、またはループの外で使用されていない変数がある場合、コンパイラはそれらを削除または移動する可能性があることを意味します。

/* If you never use these, the compiler will probably throw them out */
int var1;
double var2;
char var3[];
PAINTSTRUCT ps;
HDC hdc;

/* Nothing here effects other code, so the code will probably be removed */
for(int i = 0; i < 100000; ++i)
{
    int j = i * 7;
}

非常に厳しいパフォーマンス要件がない限り、コードを読みやすくすることが最善の方法です。変数をより小さなスコープで使用する場合は、プログラムを高速化するためではなく、読みやすくするためにそこに配置してください。

コンピューターは、CPU とメモリを使用するだけで、あなたが話しているタイプのコードを実行するのが得意です。実際にパフォーマンスが向上するのは、ネットワークやディスクからの読み取りなど、比較的低速なデバイスを扱っている場合です。そのような場合、1 バイトのメモリが問題になります。

CPU/メモリの最適化が最も効果的なのは、より複雑なアルゴリズムの場合、またはグラフィックや検索アルゴリズムのように大量のデータを扱う場合です。

これは、最適化について考えるべきではないと言っているのではありません。ほとんどのプログラムでコードの可読性を最適化し、より複雑なアルゴリズムを使用している場合、または低レベルのグラフィックスまたは複雑なデータ構造/アルゴリズムを扱っている場合にパフォーマンスを最適化し、テストした場合にのみパフォーマンスを最適化します。プログラムを少し調べてみると、実行速度が遅いことがわかります。

于 2011-04-23T22:18:39.350 に答える