Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. const OR NOT const

const OR NOT const

Scheduled Pinned Locked Moved The Lounge
14 Posts 10 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    NormDroid
    wrote on last edited by
    #1

    OK people, whilst we're debating C++, OOP, how many of you Software Engineers out there actually use the const declaration with: 1) Member functions 2) Member variables I must admit, I used to, but when your churning out 100's of lines a code a week, the 'const' keyword gets forgotten. I must try and discipline myself :) Thoughts welcome Norm

    M M O 3 Replies Last reply
    0
    • N NormDroid

      OK people, whilst we're debating C++, OOP, how many of you Software Engineers out there actually use the const declaration with: 1) Member functions 2) Member variables I must admit, I used to, but when your churning out 100's of lines a code a week, the 'const' keyword gets forgotten. I must try and discipline myself :) Thoughts welcome Norm

      M Offline
      M Offline
      Michael Dunn
      wrote on last edited by
      #2

      I forget quite often, mostly because the const modifier for methods wasn't in C++ when I learned C++. I usually remember to slap const on any GetXxx() methods, though. --Mike-- http://home.inreach.com/mdunn/ The preferred snack of 4 out of 5 Lounge readers.

      1 Reply Last reply
      0
      • N NormDroid

        OK people, whilst we're debating C++, OOP, how many of you Software Engineers out there actually use the const declaration with: 1) Member functions 2) Member variables I must admit, I used to, but when your churning out 100's of lines a code a week, the 'const' keyword gets forgotten. I must try and discipline myself :) Thoughts welcome Norm

        M Offline
        M Offline
        Mike Puddephat
        wrote on last edited by
        #3

        I try to use const everywhere, but I don't const member functions in classes derived from MFC classes. There seems to be no (or very little) const correctness in MFC classes.

        1 Reply Last reply
        0
        • N NormDroid

          OK people, whilst we're debating C++, OOP, how many of you Software Engineers out there actually use the const declaration with: 1) Member functions 2) Member variables I must admit, I used to, but when your churning out 100's of lines a code a week, the 'const' keyword gets forgotten. I must try and discipline myself :) Thoughts welcome Norm

          O Offline
          O Offline
          ov
          wrote on last edited by
          #4

          And what about compiler's optimisation? What do you think: const helps compiler to produce a faster code or not? With the best regards, Vitaly.

          A 1 Reply Last reply
          0
          • O ov

            And what about compiler's optimisation? What do you think: const helps compiler to produce a faster code or not? With the best regards, Vitaly.

            A Offline
            A Offline
            AlexMarbus
            wrote on last edited by
            #5

            Yes, it does produce faster code. For example: int MyFunction(CString str) { // Use str, but don't change it. // We don't change a member either, we just return something } or: int MyFunction(const CString& str) const { // Use str, but don't change it. // We don't change a member either, we just return something } -- Alex Marbus www.marbus.net

            A 1 Reply Last reply
            0
            • A AlexMarbus

              Yes, it does produce faster code. For example: int MyFunction(CString str) { // Use str, but don't change it. // We don't change a member either, we just return something } or: int MyFunction(const CString& str) const { // Use str, but don't change it. // We don't change a member either, we just return something } -- Alex Marbus www.marbus.net

              A Offline
              A Offline
              Andrei Zenkovitch
              wrote on last edited by
              #6

              Alex, I don't think that constness makes compiler to produce a faster code. Your example shows how using a reference as a parameter instead of a value type makes your code faster. As far as using const is concerned it only states that particular value type, pointer or referenced variable (value or object) cannot be changed; or if const is applied to object method (you cannot use const with static or global functions) it states that such function doesn't change internal state of such object. In other words it makes your design clearer by clarifying your intentions Regards, Andrei Zenkovitch

              A 1 Reply Last reply
              0
              • A Andrei Zenkovitch

                Alex, I don't think that constness makes compiler to produce a faster code. Your example shows how using a reference as a parameter instead of a value type makes your code faster. As far as using const is concerned it only states that particular value type, pointer or referenced variable (value or object) cannot be changed; or if const is applied to object method (you cannot use const with static or global functions) it states that such function doesn't change internal state of such object. In other words it makes your design clearer by clarifying your intentions Regards, Andrei Zenkovitch

                A Offline
                A Offline
                AlexMarbus
                wrote on last edited by
                #7

                Are you sure about that? I'm always certain I was always told that this construction (even without passing a reference) was faster. Anybody else has an opinion about this? Ofcourse I could be wrong, but I like some proof on that :) btw: have a nice weekend all! -- Alex Marbus www.marbus.net

                O 1 Reply Last reply
                0
                • A AlexMarbus

                  Are you sure about that? I'm always certain I was always told that this construction (even without passing a reference) was faster. Anybody else has an opinion about this? Ofcourse I could be wrong, but I like some proof on that :) btw: have a nice weekend all! -- Alex Marbus www.marbus.net

                  O Offline
                  O Offline
                  Oz Solomon
                  wrote on last edited by
                  #8

                  Const does help compilers produce faster code. Imagine this trivial example:

                  char * const p = something;
                  char *& ref = something_else;
                  for (i = 0; i < 1000000; ++i)
                  {
                  // do something with p
                  // do something with ref
                  }

                  Now - since p is a constant pointer, the compiler knows it cannot change and can avoid reloading p each time it starts the loop. However, if const is removed from p, the compiler cannot assume that p is unchanged (for instance, "ref" can change the value of p), so it will reload p each and every time. This is a very simplified example, but you can extrapolate from there. Please note, that this kind of stuff requires some cooperation from you: If you "cheat" by casting constness away, or changing a "const" value through a reference, the optimizer might product incorrect code! -Oz --- Grab WndTabs from http://www.wndtabs.com to make your VC++ experience that much more comfortable...

                  A A 2 Replies Last reply
                  0
                  • O Oz Solomon

                    Const does help compilers produce faster code. Imagine this trivial example:

                    char * const p = something;
                    char *& ref = something_else;
                    for (i = 0; i < 1000000; ++i)
                    {
                    // do something with p
                    // do something with ref
                    }

                    Now - since p is a constant pointer, the compiler knows it cannot change and can avoid reloading p each time it starts the loop. However, if const is removed from p, the compiler cannot assume that p is unchanged (for instance, "ref" can change the value of p), so it will reload p each and every time. This is a very simplified example, but you can extrapolate from there. Please note, that this kind of stuff requires some cooperation from you: If you "cheat" by casting constness away, or changing a "const" value through a reference, the optimizer might product incorrect code! -Oz --- Grab WndTabs from http://www.wndtabs.com to make your VC++ experience that much more comfortable...

                    A Offline
                    A Offline
                    Ancient Dragon
                    wrote on last edited by
                    #9

                    In my tests using VC++ 6, the const keyword may just be superficial. The VC6 compiler is pretty darned smart about optimizing code in release mode -- unless you change the optimization flags. With a small function like you described, the same code will be produce with or without the const keyword. You can verify this yourself by turning on the flag that produces the assembly code listing. I wrote two small functions, the only difference was the use of the const keyword. The reason I also call foo3() is because without it the optimizer threw away all the code in foo1() and foo2(), since these functions did nothing with the results. The assembly code produced was identical for both foo1() and foo2(). int CMyClass::foo3(const char*) { return 0; } int CMyClass::foo1(const CString& str) { char s[255]; for(int i = 0; i < str.GetLength(); i++) s[i] = str[i]; return foo3(s);; } int CMyClass::foo2(CString& str) { char s[255]; for(int i = 0; i < str.GetLength(); i++) s[i] = str[i]; return foo3(s);; } *************************************************************************************** Here is foo1() *************************************************************************************** ; 108 : { sub esp, 256 ; 00000100H ; 109 : char s[255]; ; 110 : for(int i = 0; i < str.GetLength(); i++) xor eax, eax push esi mov esi, ecx mov ecx, DWORD PTR _str$[esp+256] mov edx, DWORD PTR [ecx] mov ecx, DWORD PTR [edx-8] test ecx, ecx jle SHORT $L71804 $L71802: ; 111 : s[i] = str[i]; mov cl, BYTE PTR [edx+eax] mov BYTE PTR _s$[esp+eax+260], cl mov ecx, DWORD PTR [edx-8] inc eax cmp eax, ecx jl SHORT $L71802 $L71804: ; 112 : return foo3(s);; *************************************************************************************** Here is foo2() *************************************************************************************** ; 117 : { sub esp, 256 ; 00000100H ; 118 : char s[255]; ; 119 : for(int i = 0; i < str.GetLength(); i++) xor eax, eax push esi mov esi, ecx mov ecx, DWORD PTR _str$[esp+256] mov edx, DWORD PTR [ecx] mov ecx, DWORD PTR [edx-8] test ecx, ecx jle SHORT $L71813 $L71811: ; 120 : s[i] = str[i]; mov cl, BYTE PTR [edx+eax] mov BYTE PTR _s$[esp+eax+260], cl mov ecx, DWORD PTR [edx-8] inc eax cmp eax, ecx jl SHORT $L71811 $L71813: ; 121 : return foo3(s);;

                    L O 2 Replies Last reply
                    0
                    • A Ancient Dragon

                      In my tests using VC++ 6, the const keyword may just be superficial. The VC6 compiler is pretty darned smart about optimizing code in release mode -- unless you change the optimization flags. With a small function like you described, the same code will be produce with or without the const keyword. You can verify this yourself by turning on the flag that produces the assembly code listing. I wrote two small functions, the only difference was the use of the const keyword. The reason I also call foo3() is because without it the optimizer threw away all the code in foo1() and foo2(), since these functions did nothing with the results. The assembly code produced was identical for both foo1() and foo2(). int CMyClass::foo3(const char*) { return 0; } int CMyClass::foo1(const CString& str) { char s[255]; for(int i = 0; i < str.GetLength(); i++) s[i] = str[i]; return foo3(s);; } int CMyClass::foo2(CString& str) { char s[255]; for(int i = 0; i < str.GetLength(); i++) s[i] = str[i]; return foo3(s);; } *************************************************************************************** Here is foo1() *************************************************************************************** ; 108 : { sub esp, 256 ; 00000100H ; 109 : char s[255]; ; 110 : for(int i = 0; i < str.GetLength(); i++) xor eax, eax push esi mov esi, ecx mov ecx, DWORD PTR _str$[esp+256] mov edx, DWORD PTR [ecx] mov ecx, DWORD PTR [edx-8] test ecx, ecx jle SHORT $L71804 $L71802: ; 111 : s[i] = str[i]; mov cl, BYTE PTR [edx+eax] mov BYTE PTR _s$[esp+eax+260], cl mov ecx, DWORD PTR [edx-8] inc eax cmp eax, ecx jl SHORT $L71802 $L71804: ; 112 : return foo3(s);; *************************************************************************************** Here is foo2() *************************************************************************************** ; 117 : { sub esp, 256 ; 00000100H ; 118 : char s[255]; ; 119 : for(int i = 0; i < str.GetLength(); i++) xor eax, eax push esi mov esi, ecx mov ecx, DWORD PTR _str$[esp+256] mov edx, DWORD PTR [ecx] mov ecx, DWORD PTR [edx-8] test ecx, ecx jle SHORT $L71813 $L71811: ; 120 : s[i] = str[i]; mov cl, BYTE PTR [edx+eax] mov BYTE PTR _s$[esp+eax+260], cl mov ecx, DWORD PTR [edx-8] inc eax cmp eax, ecx jl SHORT $L71811 $L71813: ; 121 : return foo3(s);;

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #10

                      I think you missed the point. The optimizations aren't really in the routine that contain const parameters, but in the routines that invoke routines with const parameters. Also, in your example, methods were hoisted into the invoking routines also. In general, when the compiler is invoking a method with const parameters it does know that registers that might already contain elements of that const object do not need to be reloaded. Thus, improved performance.

                      A 1 Reply Last reply
                      0
                      • A Ancient Dragon

                        In my tests using VC++ 6, the const keyword may just be superficial. The VC6 compiler is pretty darned smart about optimizing code in release mode -- unless you change the optimization flags. With a small function like you described, the same code will be produce with or without the const keyword. You can verify this yourself by turning on the flag that produces the assembly code listing. I wrote two small functions, the only difference was the use of the const keyword. The reason I also call foo3() is because without it the optimizer threw away all the code in foo1() and foo2(), since these functions did nothing with the results. The assembly code produced was identical for both foo1() and foo2(). int CMyClass::foo3(const char*) { return 0; } int CMyClass::foo1(const CString& str) { char s[255]; for(int i = 0; i < str.GetLength(); i++) s[i] = str[i]; return foo3(s);; } int CMyClass::foo2(CString& str) { char s[255]; for(int i = 0; i < str.GetLength(); i++) s[i] = str[i]; return foo3(s);; } *************************************************************************************** Here is foo1() *************************************************************************************** ; 108 : { sub esp, 256 ; 00000100H ; 109 : char s[255]; ; 110 : for(int i = 0; i < str.GetLength(); i++) xor eax, eax push esi mov esi, ecx mov ecx, DWORD PTR _str$[esp+256] mov edx, DWORD PTR [ecx] mov ecx, DWORD PTR [edx-8] test ecx, ecx jle SHORT $L71804 $L71802: ; 111 : s[i] = str[i]; mov cl, BYTE PTR [edx+eax] mov BYTE PTR _s$[esp+eax+260], cl mov ecx, DWORD PTR [edx-8] inc eax cmp eax, ecx jl SHORT $L71802 $L71804: ; 112 : return foo3(s);; *************************************************************************************** Here is foo2() *************************************************************************************** ; 117 : { sub esp, 256 ; 00000100H ; 118 : char s[255]; ; 119 : for(int i = 0; i < str.GetLength(); i++) xor eax, eax push esi mov esi, ecx mov ecx, DWORD PTR _str$[esp+256] mov edx, DWORD PTR [ecx] mov ecx, DWORD PTR [edx-8] test ecx, ecx jle SHORT $L71813 $L71811: ; 120 : s[i] = str[i]; mov cl, BYTE PTR [edx+eax] mov BYTE PTR _s$[esp+eax+260], cl mov ecx, DWORD PTR [edx-8] inc eax cmp eax, ecx jl SHORT $L71811 $L71813: ; 121 : return foo3(s);;

                        O Offline
                        O Offline
                        Oz Solomon
                        wrote on last edited by
                        #11

                        Since your code wasn't testing the same thing as the example I posted, I ran my own little test. As I will show below, it seems the the VC++ optimizer is a bit stupid regarding this particular const optimization. Here's the short program:

                        void fn_no_const(const char **p, const char ** ref)
                        {
                        for (int i = 0; i < 13; ++i)
                        {
                        std::cout << **p;
                        ++(*ref);
                        }
                        }

                        void fn_const(const char * const * const p, const char ** ref)
                        {
                        for (int i = 0; i < 13; ++i)
                        {
                        std::cout << **p;
                        ++(*ref);
                        }
                        }

                        int main(int argc, char* argv[])
                        {
                        const char *p = "Hello World!";
                        fn_no_const(&p, &p);
                        p = "Hello World!";
                        fn_const(&p, &p);
                        return 0;
                        }

                        If you look closely, you will see that under optimized conditions, the expected output should be:

                        Hello World! HHHHHHHHHHHH

                        This is because in the second function (fn_const) p is defined const all around, which should tell the optimizer that the value p points to, and p itself will never change. The optimizer should have then cached the value outside the loop. However, if you look at the disassembly, you will see the the two functions are identicle - no const optimization was performed. This is not to say that VC++ can't or doesn't do const optimization, not that other compilers won't. As a general rule, I try to stick const around everything I know to be const. Not only is it a potentially an optimization helper for the compiler, it also (sometimes) helps catch assignments where you think there shouldn't be. -Oz --- Grab WndTabs from http://www.wndtabs.com to make your VC++ experience that much more comfortable...

                        1 Reply Last reply
                        0
                        • L Lost User

                          I think you missed the point. The optimizations aren't really in the routine that contain const parameters, but in the routines that invoke routines with const parameters. Also, in your example, methods were hoisted into the invoking routines also. In general, when the compiler is invoking a method with const parameters it does know that registers that might already contain elements of that const object do not need to be reloaded. Thus, improved performance.

                          A Offline
                          A Offline
                          Ancient Dragon
                          wrote on last edited by
                          #12

                          Maybe that's the way it should work, but the VC6 compiler doesn't optimize it that way. Using the default release-version optimization method, the compiler pushes all arguments onto the stack, and calls the function or method. The invoked function copies the parameters out of stack memory into whatever registers it want to. This compiler does not support the register calling convention, where the calling functions puts arguments into registers and the invoked function uses those register values. In fact, this compiler completly ignores the register keyword altogether.

                          L 1 Reply Last reply
                          0
                          • A Ancient Dragon

                            Maybe that's the way it should work, but the VC6 compiler doesn't optimize it that way. Using the default release-version optimization method, the compiler pushes all arguments onto the stack, and calls the function or method. The invoked function copies the parameters out of stack memory into whatever registers it want to. This compiler does not support the register calling convention, where the calling functions puts arguments into registers and the invoked function uses those register values. In fact, this compiler completly ignores the register keyword altogether.

                            L Offline
                            L Offline
                            Lost User
                            wrote on last edited by
                            #13

                            That isn't what I am saying. Lets imagine this case: Routine A has a pointer to a structure called StructGeorge. StructGeorge contains some elements, namely an integer called iBob. During execution, routine A loads the value of iBob into a register. Then routine A invokes routine B which requires the pointer to StructGeorge to be passed to it. After routine B returns, routine A then performs other operations with the value of iBob. Now, if the StructGeorge pointer in routine B is defined as const, then routine A can assume that the value of iBob has not changed and thus does not need to be reloaded (assuming that iBob is still around in a register). If the pointer is not defined as const in routine B, then routine A can not make that assumption and must reload the value.

                            1 Reply Last reply
                            0
                            • O Oz Solomon

                              Const does help compilers produce faster code. Imagine this trivial example:

                              char * const p = something;
                              char *& ref = something_else;
                              for (i = 0; i < 1000000; ++i)
                              {
                              // do something with p
                              // do something with ref
                              }

                              Now - since p is a constant pointer, the compiler knows it cannot change and can avoid reloading p each time it starts the loop. However, if const is removed from p, the compiler cannot assume that p is unchanged (for instance, "ref" can change the value of p), so it will reload p each and every time. This is a very simplified example, but you can extrapolate from there. Please note, that this kind of stuff requires some cooperation from you: If you "cheat" by casting constness away, or changing a "const" value through a reference, the optimizer might product incorrect code! -Oz --- Grab WndTabs from http://www.wndtabs.com to make your VC++ experience that much more comfortable...

                              A Offline
                              A Offline
                              Atul Dharne
                              wrote on last edited by
                              #14

                              IMHO the compiler smartly makes an optimization that if your variable is not a l-value then there is no need to read once it has been read at start. So maybe if an register is free this value goes in there and there are no further reads to that variable throuhout the program. This optimization can be disable by preceding any variable with the keyword 'volatile' which turns off this optimization. So const keyword makes clear to the compiler that this variable cannot be a l-value. Using const with member functions is just a checkpoint that none of the member variables are being changed and if some coder tries changing other coder's code by assigning some values to member vars it will be flagged of as an error keeping the orig coder's intentions intact...

                              1 Reply Last reply
                              0
                              Reply
                              • Reply as topic
                              Log in to reply
                              • Oldest to Newest
                              • Newest to Oldest
                              • Most Votes


                              • Login

                              • Don't have an account? Register

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • World
                              • Users
                              • Groups