Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Class properties in stack or heap?
QtWS25 Last Chance

Class properties in stack or heap?

Scheduled Pinned Locked Moved Solved C++ Gurus
stackmemory
15 Posts 5 Posters 4.6k Views
  • 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.
  • F fcarney
    7 Nov 2019, 20:27
    int main(){
        Person person; // on stack
        Person* person2 = new Person(); // on heap
    }
    

    Whether or not the variables are on the heap or stack depends upon how the object is allocated. So all members of the class will be allocated how the object is allocated.

    E Offline
    E Offline
    Exotic_Devel
    wrote on 7 Nov 2019, 20:43 last edited by
    #4

    @fcarney

    Understand! In which case which of the two approaches I used as an example do you consider the best? And what is the reason?

    F 1 Reply Last reply 7 Nov 2019, 20:51
    0
    • F fcarney
      7 Nov 2019, 20:27
      int main(){
          Person person; // on stack
          Person* person2 = new Person(); // on heap
      }
      

      Whether or not the variables are on the heap or stack depends upon how the object is allocated. So all members of the class will be allocated how the object is allocated.

      A Offline
      A Offline
      aha_1980
      Lifetime Qt Champion
      wrote on 7 Nov 2019, 20:45 last edited by aha_1980 11 Jul 2019, 20:46
      #5

      @fcarney But note that almost all Qt objects consist of a public and a private part (the d-pointer). The private part is always on the heap, even if the corresponding object is on the stack.

      E.g.:

          QString s = "Hello world and a bit more of chars.";
          qDebug() << "sizeof(s) =" << sizeof(s) << "length(s) =" << s.length();
      

      returns: sizeof(s) = 8 length(s) = 36 on my machine, which means it takes 8 bytes stack and (36 + 1) * 2 byte heap for the actual data.

      Regards

      Edit: fixed mistake in the second sentence.

      Qt has to stay free or it will die.

      F 1 Reply Last reply 7 Nov 2019, 20:52
      4
      • E Exotic_Devel
        7 Nov 2019, 20:43

        @fcarney

        Understand! In which case which of the two approaches I used as an example do you consider the best? And what is the reason?

        F Offline
        F Offline
        fcarney
        wrote on 7 Nov 2019, 20:51 last edited by
        #6

        @Exotic_Devel said in Class properties in stack or heap?:

        which of the two approaches I used as an example do you consider the best

        It depends upon requirements. If you have an object generator that gives you items allocated on heap then a list of pointers is fine: QList<Object*> m_objList; for example. Doing dynamic allocation for the sake of dynamic allocation is not worthwhile. Keep things simple (ie QString name;) until you have a reason not to (int bigArray[] = new int[1000000000];). Consider using smart pointers as well.

        C++ is a perfectly valid school of magic.

        1 Reply Last reply
        2
        • A aha_1980
          7 Nov 2019, 20:45

          @fcarney But note that almost all Qt objects consist of a public and a private part (the d-pointer). The private part is always on the heap, even if the corresponding object is on the stack.

          E.g.:

              QString s = "Hello world and a bit more of chars.";
              qDebug() << "sizeof(s) =" << sizeof(s) << "length(s) =" << s.length();
          

          returns: sizeof(s) = 8 length(s) = 36 on my machine, which means it takes 8 bytes stack and (36 + 1) * 2 byte heap for the actual data.

          Regards

          Edit: fixed mistake in the second sentence.

          F Offline
          F Offline
          fcarney
          wrote on 7 Nov 2019, 20:52 last edited by
          #7

          @aha_1980 said in Class properties in stack or heap?:

          But note that almost all Qt objects consist of a public and a private part (the d-pointer).

          Sneaky sneaky Qt! Thanks for the tip!

          C++ is a perfectly valid school of magic.

          1 Reply Last reply
          1
          • C Offline
            C Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on 7 Nov 2019, 21:12 last edited by
            #8

            Just a nitpick - a QString does not use d-pointer implementation. That's something QObject derived classes do and QString is not one of them. The reason QString itself is small is that it's a variable sized container and the data it stores is resizable. You don't know the data size beforehand, so it requires dynamic reallocation.

            Anyway - there's no point to have pointer members to container classes i.e. QString* or QList<>*. It makes the code harder to read, it makes unnecessary extra dynamic allocations (which is slow) and it makes accessing the data slow because of the double indirection through the pointers. In general if the objects are small (as in couple basic types) and they do the "heavy" data allocations just keep them as direct members, not pointers.

            As for function parameters - if you don't modify the arguments simple types just pass by value i.e. just int instead of const int&. They fit in CPUs registers and adding references to them just makes it bigger and slower because of the indirection. For complex types (e.g. QString) always prefer const &. The const part is important because it conveys your function's interface i.e. clearly states that the function won't modify that parameter. As for pointer parameters - use them to express optionality - if you get a pointer you need to check if it's not null before you use it. With references you don't.

            So by example, this is how you should "read" function arguments:

            void func(Foo param) - function just takes a Foo, Foo is small (fits in registers) so it's better to pass it by value
            void func(const Foo& param) - function just takes a Foo, Foo is not so small so we pass it via pointer (yes, references are just syntactic sugar for pointers)
            void func(Foo& param) - function takes a Foo and modifies it
            void func(Foo* param) - function can take a Foo but it works without it too, it can modify that Foo
            void func(const Foo* param) - function can take a Foo but it works without it too, it won't modify that Foo

            A E 2 Replies Last reply 8 Nov 2019, 07:49
            5
            • C Chris Kawa
              7 Nov 2019, 21:12

              Just a nitpick - a QString does not use d-pointer implementation. That's something QObject derived classes do and QString is not one of them. The reason QString itself is small is that it's a variable sized container and the data it stores is resizable. You don't know the data size beforehand, so it requires dynamic reallocation.

              Anyway - there's no point to have pointer members to container classes i.e. QString* or QList<>*. It makes the code harder to read, it makes unnecessary extra dynamic allocations (which is slow) and it makes accessing the data slow because of the double indirection through the pointers. In general if the objects are small (as in couple basic types) and they do the "heavy" data allocations just keep them as direct members, not pointers.

              As for function parameters - if you don't modify the arguments simple types just pass by value i.e. just int instead of const int&. They fit in CPUs registers and adding references to them just makes it bigger and slower because of the indirection. For complex types (e.g. QString) always prefer const &. The const part is important because it conveys your function's interface i.e. clearly states that the function won't modify that parameter. As for pointer parameters - use them to express optionality - if you get a pointer you need to check if it's not null before you use it. With references you don't.

              So by example, this is how you should "read" function arguments:

              void func(Foo param) - function just takes a Foo, Foo is small (fits in registers) so it's better to pass it by value
              void func(const Foo& param) - function just takes a Foo, Foo is not so small so we pass it via pointer (yes, references are just syntactic sugar for pointers)
              void func(Foo& param) - function takes a Foo and modifies it
              void func(Foo* param) - function can take a Foo but it works without it too, it can modify that Foo
              void func(const Foo* param) - function can take a Foo but it works without it too, it won't modify that Foo

              A Offline
              A Offline
              aha_1980
              Lifetime Qt Champion
              wrote on 8 Nov 2019, 07:49 last edited by
              #9

              @Chris-Kawa

              Chris Kawa Moderators about 11 hours ago

              Just a nitpick - a QString does not use d-pointer implementation.

              Then have a look here:

              https://code.woboq.org/qt5/qtbase/src/corelib/text/qstring.h.html#QString::d

              Regards

              Qt has to stay free or it will die.

              C 1 Reply Last reply 8 Nov 2019, 08:18
              4
              • A aha_1980
                8 Nov 2019, 07:49

                @Chris-Kawa

                Chris Kawa Moderators about 11 hours ago

                Just a nitpick - a QString does not use d-pointer implementation.

                Then have a look here:

                https://code.woboq.org/qt5/qtbase/src/corelib/text/qstring.h.html#QString::d

                Regards

                C Offline
                C Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on 8 Nov 2019, 08:18 last edited by
                #10

                @aha_1980 said

                Then have a look here:

                Haha, nice one :) I guess that's what I get for not being more clear.
                The "d pointer" in Qt context usually refers to the Private implementation idiom (or PIMPL). QString does not use it and this is what I meant. It just happens to have a member called d becasue it refers to data.

                1 Reply Last reply
                3
                • J Offline
                  J Offline
                  JonB
                  wrote on 8 Nov 2019, 08:29 last edited by
                  #11

                  @Chris-Kawa , @aha_1980
                  I'd like to know the difference for passing/receiving as function parameter between const QString and const QString&? They both involve passing (64-bit) 8 bytes, they both increment the shared usage of the of string in the allocation table, neither allows modification (copy-on-write). Right?

                  Actually, now I think about it, that's wrong, right? const QString& does not increment the reference count, right? And that's a big difference....

                  1 Reply Last reply
                  1
                  • C Offline
                    C Offline
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on 8 Nov 2019, 09:17 last edited by Chris Kawa 11 Aug 2019, 09:18
                    #12

                    Passing by const Foo calls copy constructor. Depending on a class this might be cheap or expensive. QString (and all implicitly shared Qt classes) have a mechanism that makes this copy not so expensive - it just copies data pointer and bumps a refcount. This is cheaper than copying whole data, but still more expensive than just copying a pointer when passing via const Foo&. In short - except for small types that don't involve any "copy logic" don't copy when you don't explicitly want a copy.

                    1 Reply Last reply
                    5
                    • C Chris Kawa
                      7 Nov 2019, 21:12

                      Just a nitpick - a QString does not use d-pointer implementation. That's something QObject derived classes do and QString is not one of them. The reason QString itself is small is that it's a variable sized container and the data it stores is resizable. You don't know the data size beforehand, so it requires dynamic reallocation.

                      Anyway - there's no point to have pointer members to container classes i.e. QString* or QList<>*. It makes the code harder to read, it makes unnecessary extra dynamic allocations (which is slow) and it makes accessing the data slow because of the double indirection through the pointers. In general if the objects are small (as in couple basic types) and they do the "heavy" data allocations just keep them as direct members, not pointers.

                      As for function parameters - if you don't modify the arguments simple types just pass by value i.e. just int instead of const int&. They fit in CPUs registers and adding references to them just makes it bigger and slower because of the indirection. For complex types (e.g. QString) always prefer const &. The const part is important because it conveys your function's interface i.e. clearly states that the function won't modify that parameter. As for pointer parameters - use them to express optionality - if you get a pointer you need to check if it's not null before you use it. With references you don't.

                      So by example, this is how you should "read" function arguments:

                      void func(Foo param) - function just takes a Foo, Foo is small (fits in registers) so it's better to pass it by value
                      void func(const Foo& param) - function just takes a Foo, Foo is not so small so we pass it via pointer (yes, references are just syntactic sugar for pointers)
                      void func(Foo& param) - function takes a Foo and modifies it
                      void func(Foo* param) - function can take a Foo but it works without it too, it can modify that Foo
                      void func(const Foo* param) - function can take a Foo but it works without it too, it won't modify that Foo

                      E Offline
                      E Offline
                      Exotic_Devel
                      wrote on 9 Nov 2019, 12:17 last edited by
                      #13

                      @Chris-Kawa said in Class properties in stack or heap?:

                      Anyway - there's no point to have pointer members to container classes i.e. QString* or QList<>*. It makes the code harder to read, it makes unnecessary extra dynamic allocations (which is slow) and it makes accessing the data slow because of the double indirection through the pointers.

                      Hello!

                      Does this apply to QMap as well?

                      J C 2 Replies Last reply 9 Nov 2019, 13:06
                      0
                      • E Exotic_Devel
                        9 Nov 2019, 12:17

                        @Chris-Kawa said in Class properties in stack or heap?:

                        Anyway - there's no point to have pointer members to container classes i.e. QString* or QList<>*. It makes the code harder to read, it makes unnecessary extra dynamic allocations (which is slow) and it makes accessing the data slow because of the double indirection through the pointers.

                        Hello!

                        Does this apply to QMap as well?

                        J Offline
                        J Offline
                        JonB
                        wrote on 9 Nov 2019, 13:06 last edited by JonB 11 Sept 2019, 14:30
                        #14

                        @Exotic_Devel
                        Yes, he's suggesting you should only bother to create QMap map variables, you don't need to go QMap *pMap = new QMap(). The QMap structure itself is small, it does not include the mapping table. This will apply to all the classes listed in https://doc.qt.io/qt-5/containers.html#the-container-classes (you'll see QMap there). Plus some others like QString, QByteArray and QVariant, but I don't know where you find a comprehensive list of those. See @Chris-Kawa's post below.

                        1 Reply Last reply
                        0
                        • E Exotic_Devel
                          9 Nov 2019, 12:17

                          @Chris-Kawa said in Class properties in stack or heap?:

                          Anyway - there's no point to have pointer members to container classes i.e. QString* or QList<>*. It makes the code harder to read, it makes unnecessary extra dynamic allocations (which is slow) and it makes accessing the data slow because of the double indirection through the pointers.

                          Hello!

                          Does this apply to QMap as well?

                          C Offline
                          C Offline
                          Chris Kawa
                          Lifetime Qt Champion
                          wrote on 9 Nov 2019, 14:21 last edited by
                          #15

                          @Exotic_Devel In the link I posted is a full list of implicitly shared classes: list of classes. What I said applies to all of them and yes, QMap is one of them.

                          1 Reply Last reply
                          3

                          13/15

                          9 Nov 2019, 12:17

                          • Login

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