简体   繁体   中英

C++ programming efficiency

Here is some code that I copied from the 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.   
} 
} 

I am probably wrong but I thought that everytime the compiler ran a statement like any one of these:

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

the computer would create a new variable. At least that would be the logical thing to think because that is what you write when you want to create a new variable, right?

I also always thought that if you had a block of code like this:

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

the computer would create 100 different variables all with the same name sum and some value that was contained in i

In the sample code above, the function WndProc will be called many many times over the course of the program, however the two variables that the function creates called "ps" and "hdc" will only be used some of the times that the function executes.

So would the computer be making lots of separate, extra PAINTSTRUCT and HDC variables that it will never use?
Would it not be at least slightly more efficiant to declare "ps" and "hdc" after case WM_PAINT: like this?

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

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

I am probably wrong but i thought that everytime the compiler ran a statement like any one of these:

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

the computer would create a new variable.

These variables correspond to storage space at runtime. As they are locals, they likely live on the stack and allocating space for these locals is as simple as moving the stack pointer. This is blazingly fast.

i also always thought that if you had a block of code like this: for(int i = 0; i < 100; i++) int sum = i;

the computer would create 100 different variables all with the same name "sum" and some value that was contained in "i"

Likely what will happen here is that the same location on the stack will be reused for each iteration of the loop.

Would it not be at least slightly more efficiant to declare "ps" and "hdc" after case WM_PAINT: like this?

No, they are locals, they are likely allocated on the stack and their space is reserved as soon as the method is entered independent of where you declare them in the code.

Finally, worry about the performance here is a micro-optimization at best. Focus on the meaning of your code. Let the compiler translate it as effectively as it can into executable code. Only if you have performance issues that don't meet your customer's expected performance requirements should you start worrying.

You are correct that the computer will be declaring a lot of local variables, but fortunately this is extremely efficient. The compiler usually outputs the code to produce local variables as a single assembly instruction when the function is first called, and so the overhead of creating these variables is negligible. In your loop example, the compiler usually doesn't create and destroy the variable multiple times. Rather, it creates it once, them reuses the space on each iteration of the loop. In other words, the variable is logically being created and destroyed on each iteration, but in the generated code it actually gets shared across multiple iterations.

As a mor general rule, don't worry about the efficiency of your programs unless you have a specific reason to believe that your performance is below what it should be. Your priority should be to write clean, elegant code rather than optimized code the first time around, since without actually running the program it's very hard to know whether your optimizations will have a useful effect on the program's runtime. Usually you would use a profiler to determine what spots of the code are slow, then focus your optimization efforts there.

For a primitive local variable -- pointers, int, double, float, etc, -- and arrays of primitives, declaring a variable does indeed "allocate" space for it, but all that actually happens is the compiler says "I'm going to call this spot on the stack, three words below the stack pointer, i ." No actual computation happens -- no instructions are executed at all! Therefore declaring "sum" inside or outside the loop makes absolutely no difference at all!

For a locally declared class instance, however, things are different. Declaring the object means that the constructor is going to be called when the block is entered, and the destructor will be called when it's exited, and that does result in instructions being executed -- so there you need to be careful.

the computer would create a new variable

This is only superficially true. Technically what the processor actually does is move the stack pointer to a certain length. If the variables you declare don't have any constructors then the overhead for this action is virtually zero.

so would the computer be making lots of separate, extra PAINTSTRUCT and HDC variables that it will never use?

No, this is not true, once the function returns all of the stack space allocated for these variables is reclaimed and nothing is wasted.

Would it not be at least slightly more efficiant to declare "ps" and "hdc" after case WM_PAINT: like this?

Not likely. The compiler is likely to see the declarations and allocated space for these variables o the stack no matter where you put the declaration for them. Again, that's true for as long as the variables don't have constructors. If they do, then putting them in the case would save the call for the constructor.

The compiler will make significant changes to your code, as long as it has the same outcome. Especially in a release (non-debug) build.

This means if you have unused code, declare variables too soon, or have variables that aren't used outside loops, the compiler may get rid of or move them.

/* 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;
}

Unless you have really strong performance requirements, the best things you can do is make your code more readable. If a variable is used in a smaller scope, place it there because it is easier to read, not because it might make your program faster.

Computers are really good at running the type of code you are talking about, where you are just using the CPU and memory. Places where you can actually get a good performance improvement are when you are dealing with relatively slow devices, like the network, or reading from the disk. In those cases, single bytes of memory matter.

The place where CPU/memory optimizations make the most sense is in more complex algorithms, or when you are working with a lot of data, like a graphics or search algorithm.

This isn't to say that you shouldn't think about optimization - just that you should pick your battles. Optimize the readability of your code in most of your program, and optimize the performance when you have a more complex algorithm, or you're dealing with low-level graphics or complex data structures/algorithms, and then, only when you've tested your program out a bit, and find out it is running slow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM