Declare variables at top of function or in separate scopes?

后端 未结 9 1114
温柔的废话
温柔的废话 2020-12-01 01:47

Which is preferred, method 1 or method 2?

Method 1:

LRESULT CALLBACK wpMainWindow(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    switch (         


        
相关标签:
9条回答
  • 2020-12-01 01:51

    For Java programming language, the common practice is to declare local variables only when needed in a method.

    void foo(int i) {
      if (i == 1)
        return;
      Map map1 = new HashMap();
      if (i == 2)
        return;
      Map map2 = new HashMap();
    }
    

    For C++ programming language, I also suggest the same practice since declaring variables with a non-trivial constructor involves execution cost. Putting all these declarations at the method beginning causes unneeded cost if some of these variables will be used.

    void foo(int i) 
    {
      if (i == 1)
        return;
      std::map<int, int> map1; // constructor is executed here
      if (i == 2)
        return;
      std::map<int, int> map2; // constructor is executed here
    }
    

    For C, the story is different. It depends on architecture and compiler. For x86 and GCC, putting all the declarations at function beginning and declaring variables only when needed have the same performance. The reason is that C variables don't have a constructor. And the effect on stack memory allocation by these two approaches is the same. Here is an example:

    void foo(int i)
    {
      int m[50];
      int n[50];
      switch (i) {
        case 0:
          break;
        case 1:
          break;
        default:
          break;
      }
    }
    
    void bar(int i) 
    {
      int m[50];
      switch (i) {
        case 0:
          break;
        case 1:
          break;
        default:
          break;
      }
      int n[50];
    }
    

    For both functions, the assembly code for stack manipulation is:

    pushl   %ebp
    movl    %esp, %ebp
    subl    $400, %esp
    

    Putting all the declarations at function beginning is common in Linux kernel code.

    0 讨论(0)
  • 2020-12-01 01:54

    Define the variables in the narrowest scope where they are relevant. There's no reason to use Method 2 above in my opinion.

    Stack space is only likely to be used when the variables are in scope. As @paxdiablo points out, your locals may wind up in registers rather than on the stack, if the compiler can find the space for them.

    0 讨论(0)
  • 2020-12-01 02:03

    Whether something's allocated on the stack in case 1 is implementation defined. Implementations aren't even required to have a stack.

    It's usually no slower to do so since the operation tends to be a simple subtraction (for a downward growing stack) of one value from the stack pointer for the entire local variable area.

    The thing that's important here is that the scope should be as local as possible. In other words, declare your variables as late as possible and only keep them around as long as needed.

    Note that declaring here is at a different abstraction level to allocating space for them. The actual space may be allocated at the start of the function (implementation level) but you can only use those variables while they're scoped (C level).

    Locality of information is important, just like its cousin, encapsulation.

    0 讨论(0)
  • 2020-12-01 02:03

    I like Method 3:

    LRESULT wpMainWindowPaint(HWND hwnd)
    {
        HDC hdc;
        PAINTSTRUCT ps;
    
        RECT rc;
        GetClientRect(hwnd, &rc);           
    
        hdc = BeginPaint(hwnd, &ps);
        // drawing here
        EndPaint(hwnd, &ps);
        return 0;
    }
    
    LRESULT CALLBACK wpMainWindow(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
        switch (msg)
        {
            case WM_PAINT:      return wpMainWindowPaint(hwnd);
            default:            return DefWindowProc(hwnd, msg, wparam, lparam);
        }
    }
    

    If it deserves its own scope for organization purposes, it deserves its own function. If you're worried about function call overhead, make it inline.

    0 讨论(0)
  • 2020-12-01 02:03

    Memory allocation is not specified in the Standard to this detail, so for a real answer you'll have to specify compiler and platform. It's not going to matter for performance.

    What you want is readability, and in general that's done by declaring variables in the smallest usable scope, and preferably when you can immediately initialize them with reasonable values. The smaller a variable's scope, the less it can potentially interact with the rest of the program in unpredictable ways. The closer the declaration to initialization, the less opportunity for anything bad to happen.

    What would probably be better is something like

    RECT rc;
    GetClientRect(hwnd, &rc);
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    

    This is for C++. For C, the rule is similar, except that earlier versions of C required all the variables to be declared at the top of a block.

    0 讨论(0)
  • 2020-12-01 02:03

    There's no need to pollute the stack with variables that are possibly never used. Allocate your vars right before they are used. Overlooking the RECT rc and the subsequent call to GetClientRect, Ben Voight's method is the way to go.

    0 讨论(0)
提交回复
热议问题