Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt (C++) - method argument optimization?
Forum Updated to NodeBB v4.3 + New Features

Qt (C++) - method argument optimization?

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 4 Posters 3.5k Views 2 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.
  • raven-worxR Offline
    raven-worxR Offline
    raven-worx
    Moderators
    wrote on last edited by
    #2

    the most important advantage is simply performance.
    Since you pass a const-reference of a list it can be passed directly to the calling function. The const ensures that it is not altered by the callee.
    When you pass it by value the whole list needs to be copied before it is passed to the callee. Depending on the data type this can be a very fatal operation which slows down your application. For small lists with simply data-types you wont recognize a difference.
    But it's good practice to do so and a big advantage of C++ to give you more control of the memory.

    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
    If you have a question please use the forum so others can benefit from the solution in the future

    1 Reply Last reply
    0
    • jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #3

      No need to use references for basic types.
      A reference is besides the scene a pointer, since an int has the same size as a pointer there is no benefit to pass int by const reference (other basic types have similar size, so no need for references).
      For signals/slots same rules apply.

      The compiler does not do it for you because you could change the parameter in your function/method by MISTAKE. So, it is up to you to tell the compiler whether you're going to change the parameter (non const reference) or not. Usually you should know what you are doing and write the code accordingly.

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      raven-worxR 1 Reply Last reply
      0
      • jsulmJ jsulm

        No need to use references for basic types.
        A reference is besides the scene a pointer, since an int has the same size as a pointer there is no benefit to pass int by const reference (other basic types have similar size, so no need for references).
        For signals/slots same rules apply.

        The compiler does not do it for you because you could change the parameter in your function/method by MISTAKE. So, it is up to you to tell the compiler whether you're going to change the parameter (non const reference) or not. Usually you should know what you are doing and write the code accordingly.

        raven-worxR Offline
        raven-worxR Offline
        raven-worx
        Moderators
        wrote on last edited by raven-worx
        #4

        @jsulm said:

        No need to use references for basic types.

        dangerous advice for a C++ beginner.
        Imagine a list with a few hundrets of thousands int values contained. All values need to be traversed and copied in memory. And this is sub-optimal when it can be avoided.

        I forgot to mention that many classes are implicitly shared in Qt. So like the QList for example.
        Nevertheless the const-reference way is the recommended one in all cases.

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        jsulmJ 1 Reply Last reply
        0
        • raven-worxR raven-worx

          @jsulm said:

          No need to use references for basic types.

          dangerous advice for a C++ beginner.
          Imagine a list with a few hundrets of thousands int values contained. All values need to be traversed and copied in memory. And this is sub-optimal when it can be avoided.

          I forgot to mention that many classes are implicitly shared in Qt. So like the QList for example.
          Nevertheless the const-reference way is the recommended one in all cases.

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #5

          @raven-worx I was talking about basic types like int, double, char and so on not about complex types like lists.

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          raven-worxR 1 Reply Last reply
          0
          • jsulmJ jsulm

            @raven-worx I was talking about basic types like int, double, char and so on not about complex types like lists.

            raven-worxR Offline
            raven-worxR Offline
            raven-worx
            Moderators
            wrote on last edited by
            #6

            ah k...got it after reading it a second time

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            0
            • M Offline
              M Offline
              maximus
              wrote on last edited by maximus
              #7

              Thanks for the tips guys,

              I will revisit my code and change to "const reference" where I don't modify the argument and the argument is something else than a basic type (int, double).

              I think jsulm meant basic type that are not in container, e.g (int and not QList<int>)
              Also what I meant for the compiler is to detect wheter we change the argument, if so, pass it by value. If not, pass it by reference. But of course C++ let you modify function argument, and this would not let you do that (not a bad thing IMO..)


              Free Indoor Cycling Software - https://maximumtrainer.com

              1 Reply Last reply
              0
              • M Offline
                M Offline
                maximus
                wrote on last edited by maximus
                #8

                Let say I have a constructor with a "const QVector<int>& vecId"
                My goal is that I can manipulate this list but not modify it. (read only).

                So I assign this list to a local QList of this Object.

                this.vecId = vecId;  // vecId is of type QVector<int> vecId2
                
                qDebug() << "THIS IS THE LENGTH BEFORE REMOVAL " << this->vecId .size();
                this->vecId .removeAt(0);
                qDebug() << "THIS IS THE LENGTH AFTER REMOVAL " << this->vecId .size();
                

                Here I can still modify the QList
                Is there a way to optimize this code or am I forced to pass the whole list by value like I was doing before? Thanks

                Interesting, maybe I don't need to do it


                Free Indoor Cycling Software - https://maximumtrainer.com

                1 Reply Last reply
                0
                • Chris KawaC Offline
                  Chris KawaC Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on last edited by
                  #9

                  @maximus said:

                  I wonder why the compiler doesn't do this stuff for us, detect if we modify the method argument and optimize accordingly

                  Because it can't. You can pass that parameter into another function. It can get an address of it and modify that. It can const_cast the parameter. It can use a goto into a code that modifies it. It can do million other crazy stuff with it. Compiler can't make guesses. It simply needs to be perfectly deterministic. The only way this sort of automatic optimization was possible is if your whole program was a constexpr evaluated at compile time, but then there would be no point in optimizing it at all, and such program would be useless anyway.

                  Here I can still modify the QList

                  No. You can (and did) modify a copy of the list. The original is intact.

                  Interesting, maybe I don't need to do it

                  Implicit sharing is meant to help moving large structures around but it's not free! It is still a copy of the object. A copy constructor is called. An internal reference count is changed as an atomic operation. The data is not copied (initially) but still a lot is going on. A const reference is basically a pointer on the stack, or even in a cpu register, which is as close to "free" as you will get.

                  M 1 Reply Last reply
                  0
                  • Chris KawaC Chris Kawa

                    @maximus said:

                    I wonder why the compiler doesn't do this stuff for us, detect if we modify the method argument and optimize accordingly

                    Because it can't. You can pass that parameter into another function. It can get an address of it and modify that. It can const_cast the parameter. It can use a goto into a code that modifies it. It can do million other crazy stuff with it. Compiler can't make guesses. It simply needs to be perfectly deterministic. The only way this sort of automatic optimization was possible is if your whole program was a constexpr evaluated at compile time, but then there would be no point in optimizing it at all, and such program would be useless anyway.

                    Here I can still modify the QList

                    No. You can (and did) modify a copy of the list. The original is intact.

                    Interesting, maybe I don't need to do it

                    Implicit sharing is meant to help moving large structures around but it's not free! It is still a copy of the object. A copy constructor is called. An internal reference count is changed as an atomic operation. The data is not copied (initially) but still a lot is going on. A const reference is basically a pointer on the stack, or even in a cpu register, which is as close to "free" as you will get.

                    M Offline
                    M Offline
                    maximus
                    wrote on last edited by maximus
                    #10

                    @Chris-Kawa

                    I was thinking something like this method

                    void printString(QString s) {
                        qDebug() << s;
                    /*
                    The compiler could detect that nothing was assigned to "s" since it can read the whole function, so it replace the argument with const QString& s.  In other words, the value of "s" after function execution is the same value as before for any input possible.
                    */
                    }
                    

                    I will read more on C++. For now, I will only replace my getter functions and add const at the end of them. Hopefully I can get the benefit on implicit sharing without doing too much work.
                    I just find it a bit sad the learning curve of C++ compared with other languages. That's what you get for starting with an "easy" language that doesn't have pointers and do memory management for you I guess. Thanks!


                    Free Indoor Cycling Software - https://maximumtrainer.com

                    1 Reply Last reply
                    0
                    • Chris KawaC Offline
                      Chris KawaC Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on last edited by
                      #11

                      I was thinking something like this method

                      You're forgetting that in c++ you can overload operators.
                      The signature of << is QDebug & operator<<(const QString & s) and that to some extent helps.
                      But what if it was QDebug & operator<<(QString& s)? How would the compiler know then that operator<< does not modify s internally?

                      I said to some extent because the compiler is really fighting an uphill battle.
                      For example the first line in that operator method could be something like

                      QString& foo = const_cast<QString&>(s);
                      foo = "gotcha!";
                      

                      If you think a compiler can follow this then what if the implementation was in a different translation unit or even in a different library? Of course the example is contrived and plain silly, but none the less valid c++ that a compiler must deal with correctly and not optimize stuff away.

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        maximus
                        wrote on last edited by
                        #12

                        Thanks Kawa, that example made me understood the whole problem.
                        Since any method can modify it's argument in C++, we need to had const to explicitly state that it does not.
                        I just never use this C++ feature (passing by reference without const), so that's probably why it was not natural for me.
                        I will go back to the books! I just feel changing an argument is "wrong" and I use a return value to do it, old habits...


                        Free Indoor Cycling Software - https://maximumtrainer.com

                        1 Reply Last reply
                        0
                        • Chris KawaC Offline
                          Chris KawaC Offline
                          Chris Kawa
                          Lifetime Qt Champion
                          wrote on last edited by
                          #13

                          @maximus said:

                          I just feel changing an argument is "wrong" and I use a return value to do it, old habits

                          If possible you should definitely avoid non-const reference arguments. Returning a value instead of modifying an argument is actually a very good thing in many situations. The optimizer will like that a lot.

                          Since you're up to reading about c++ you might want to look up return value optimization.
                          The fastest way to copy is to avoid copying in the first place ;)

                          Happy coding.

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved