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 pointer and non pointer member function question..
QtWS25 Last Chance

class pointer and non pointer member function question..

Scheduled Pinned Locked Moved Solved C++ Gurus
16 Posts 4 Posters 2.3k 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.
  • U Offline
    U Offline
    U7Development
    wrote on last edited by
    #1

    Hi all..

    What is the difference between these two classes on memory?

    class Alpha{
         ObjectA a0;
         ObjectB b0;
    };
    
    class Beta{
         ObjectA* pA {nullptr};
         ObjectB* pB {nullptr};
    };
    
    int main(){
    
         //_a is located on heap, does instances a0 & b0 are located on heap too even if they are not pointers?
         Alpha* _a = new Alpha;     
         
         //_b is located in stack, does instances pA & pB are located on stack even if they are pointers?
         Beta _b;    
         return 0;
    }
    
    

    I have a confusion with this.
    Thanks

    JonBJ 1 Reply Last reply
    0
    • U U7Development

      Hi all..

      What is the difference between these two classes on memory?

      class Alpha{
           ObjectA a0;
           ObjectB b0;
      };
      
      class Beta{
           ObjectA* pA {nullptr};
           ObjectB* pB {nullptr};
      };
      
      int main(){
      
           //_a is located on heap, does instances a0 & b0 are located on heap too even if they are not pointers?
           Alpha* _a = new Alpha;     
           
           //_b is located in stack, does instances pA & pB are located on stack even if they are pointers?
           Beta _b;    
           return 0;
      }
      
      

      I have a confusion with this.
      Thanks

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @U7Development said in class pointer and non pointer member function question..:

      //_a is located on heap, does instances a0 & b0 are located on heap too even if they are not pointers?

      Yes. The ObjectA/B instances are located inside the new Aplha, which is on the heap here.

      //_b is located in stack, does instances pA & pB are located on stack even if they are pointers?

      The pointers are in the Beta stack object. This says nothing at all about where _b.pA or _b.pB point to (they are initially nullptr), no ObjectA/B are allocated yet. If/when you set these, they will point to wherever the objects you set them to are.

      U 1 Reply Last reply
      2
      • JonBJ JonB

        @U7Development said in class pointer and non pointer member function question..:

        //_a is located on heap, does instances a0 & b0 are located on heap too even if they are not pointers?

        Yes. The ObjectA/B instances are located inside the new Aplha, which is on the heap here.

        //_b is located in stack, does instances pA & pB are located on stack even if they are pointers?

        The pointers are in the Beta stack object. This says nothing at all about where _b.pA or _b.pB point to (they are initially nullptr), no ObjectA/B are allocated yet. If/when you set these, they will point to wherever the objects you set them to are.

        U Offline
        U Offline
        U7Development
        wrote on last edited by
        #3

        @JonB ok! Got it now..

        So for instance, I don't need to use Qt classes as pointers if my whole class will be created on the heap isn't?..

        For instance

        class Alpha : public QDialog{
              QLabel myLabel;  //this should be fine, anyway will be on heap
              QLabel* myLabelPointer {nullptr}; //this should not be necessary.
        
        };
        
        into main (){
            Alpha* a = new Alpha;
        }
        

        Is this correct?

        JonBJ 1 Reply Last reply
        0
        • U U7Development

          @JonB ok! Got it now..

          So for instance, I don't need to use Qt classes as pointers if my whole class will be created on the heap isn't?..

          For instance

          class Alpha : public QDialog{
                QLabel myLabel;  //this should be fine, anyway will be on heap
                QLabel* myLabelPointer {nullptr}; //this should not be necessary.
          
          };
          
          into main (){
              Alpha* a = new Alpha;
          }
          

          Is this correct?

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #4

          @U7Development
          In a word, yes.

          QLabel myLabel;  //this should be fine, anyway will be on heap
          

          This class member variable is created when any Alpha is created, and destroyed when that Alpha instance is deleted or goes out of scope. The nice thing is that nobody has to delete this variable, because its destruction is automatic, when Alpha is destroyed.

          QLabel* myLabelPointer {nullptr}; //this should not be necessary.
          

          This means that somebody somewhere has to go myLabelPointer = new QLabel(). And that means it will need explicit deleteing. Either you can put delete myLabelPointer into Alpha::~Alpha() destructor, or when you create it go myLabelPointer = new QLabel(this) (or use a call which puts it on the dialog, which will do this at some point). Now because of the parent = this, when the QDialog gets destroyed it will have Qt code which goes down all the widgets it owns this way and call delete on them for you.

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

            It's worth noting that while it's fine to use a non pointer variable in a simple case like this, an average ui is far more complex and it becomes harder to track the order of the children. Keep in mind that placing a widget in a layout of another widget or manually reparenting it will also make the parent try to delete that widget.

            So, if you have something like

            class Alpha : public QDialog
            {
               QLabel myLabel;
            };
            

            the lifetime timeline is:

            Alpha is constructed
            myLabel is constructed
            myLabel is placed somewhere in Alpha -> Alpha becomes parent
            Alpha destructor hits
            myLabel is destroyed -> detaches from Alpha
            Alpha base QObject destructor hits, no children to delete
            Alpha is destroyed
            

            but, if you do something like

            class Alpha : public QDialog
            {
               QGroupBox myGroupBox; //just an example
               QLabel myLabel;
            };
            

            and do something like:

            myGroupBox.layout()->addWidget(&myLabel);
            

            it becomes problematic:

            Alpha is constructed
            myGroupBox is constructed
            myLabel is constructed
            myGroupBox is placed somewhere in Alpha -> Alpha becomes parent
            myLabel is placed somewhere in myGroupBox-> myGroupBox becomes parent
            Alpha destructor hits
            myGroupBox destructor hits -> tries to free all children, including calling delete on myLabel
            myLabel destructor hits -> oh no! crash
            

            You could avoid this particular problem by reversing order of the variables, but you can see how easily it can get messy when talking about dozens of widgets in an average dialog. So while dynamic allocation is not something to be taken lightly entire Qt is designed in a way that makes it a lot easier and less error prone if you use it.

            JonBJ 1 Reply Last reply
            3
            • Chris KawaC Chris Kawa

              It's worth noting that while it's fine to use a non pointer variable in a simple case like this, an average ui is far more complex and it becomes harder to track the order of the children. Keep in mind that placing a widget in a layout of another widget or manually reparenting it will also make the parent try to delete that widget.

              So, if you have something like

              class Alpha : public QDialog
              {
                 QLabel myLabel;
              };
              

              the lifetime timeline is:

              Alpha is constructed
              myLabel is constructed
              myLabel is placed somewhere in Alpha -> Alpha becomes parent
              Alpha destructor hits
              myLabel is destroyed -> detaches from Alpha
              Alpha base QObject destructor hits, no children to delete
              Alpha is destroyed
              

              but, if you do something like

              class Alpha : public QDialog
              {
                 QGroupBox myGroupBox; //just an example
                 QLabel myLabel;
              };
              

              and do something like:

              myGroupBox.layout()->addWidget(&myLabel);
              

              it becomes problematic:

              Alpha is constructed
              myGroupBox is constructed
              myLabel is constructed
              myGroupBox is placed somewhere in Alpha -> Alpha becomes parent
              myLabel is placed somewhere in myGroupBox-> myGroupBox becomes parent
              Alpha destructor hits
              myGroupBox destructor hits -> tries to free all children, including calling delete on myLabel
              myLabel destructor hits -> oh no! crash
              

              You could avoid this particular problem by reversing order of the variables, but you can see how easily it can get messy when talking about dozens of widgets in an average dialog. So while dynamic allocation is not something to be taken lightly entire Qt is designed in a way that makes it a lot easier and less error prone if you use it.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @Chris-Kawa
              That's frightening :(

              So.... keeping it simple the rule is: it's OK to declare member instances in, say, QDialog provided all of them are put directly onto the dialog, so it stays their parent. But here you want to re-parent the label onto the group box, so all hell breaks loose. And you'd have been better doing these via pointers and

              myGroupBoxPointer = new QGroupBox(this);
              myLabelPointer = new QLabel;
              myGroupBoxPointer->layout()->addWidget(myLabelPointer);
              

              Is that about right?

              When I see @SGaist often recommending people declare a QTimer someone needs as a member instance (not pointer), this turns out to be "safe" without having to worry about it because you're not going to re-parent a timer. The problem of having instance variables will come, in practice, when you are declaring QWidgets, because there you do re-parent.

              Is that about right too?

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

                @JonB Yup, about right. It's not only with widgets though. It's the same with any QObject but maybe easier to trip over QWidgets because it's easier to reparent them implicitly without calling setParent.

                In a nutshell:

                // any scope
                {
                    QObject a;
                    QObject b;
                }
                

                it's ok for a to become the parent of b, but for reverse to work you'd have to explicitly de-parent a before the end of scope, otherwise there's double-delete problem.

                My super relative, super simplified, super context dependent rule of thumb: if it has a parent allocate dynamically.

                JonBJ kshegunovK 2 Replies Last reply
                4
                • Chris KawaC Chris Kawa

                  @JonB Yup, about right. It's not only with widgets though. It's the same with any QObject but maybe easier to trip over QWidgets because it's easier to reparent them implicitly without calling setParent.

                  In a nutshell:

                  // any scope
                  {
                      QObject a;
                      QObject b;
                  }
                  

                  it's ok for a to become the parent of b, but for reverse to work you'd have to explicitly de-parent a before the end of scope, otherwise there's double-delete problem.

                  My super relative, super simplified, super context dependent rule of thumb: if it has a parent allocate dynamically.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #8

                  @Chris-Kawa
                  Funnily enough, a whole convo related to this is going on in https://forum.qt.io/topic/124322/avoid-dangling-qtimer-object atm.

                  1 Reply Last reply
                  0
                  • U Offline
                    U Offline
                    U7Development
                    wrote on last edited by
                    #9

                    thank you very much for such rich information..

                    1 Reply Last reply
                    0
                    • Chris KawaC Chris Kawa

                      @JonB Yup, about right. It's not only with widgets though. It's the same with any QObject but maybe easier to trip over QWidgets because it's easier to reparent them implicitly without calling setParent.

                      In a nutshell:

                      // any scope
                      {
                          QObject a;
                          QObject b;
                      }
                      

                      it's ok for a to become the parent of b, but for reverse to work you'd have to explicitly de-parent a before the end of scope, otherwise there's double-delete problem.

                      My super relative, super simplified, super context dependent rule of thumb: if it has a parent allocate dynamically.

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      @Chris-Kawa said in class pointer and non pointer member function question..:

                      My super relative, super simplified, super context dependent rule of thumb: if it has a parent allocate dynamically.

                      Eh! I hate allocating a single pointer on the heap, so as a consequence I hate that rule of thumb. Nothing personal, but it's just terribly inefficient, even if manually detaching the parent feels so clumsy.

                      Read and abide by the Qt Code of Conduct

                      Chris KawaC 1 Reply Last reply
                      1
                      • kshegunovK kshegunov

                        @Chris-Kawa said in class pointer and non pointer member function question..:

                        My super relative, super simplified, super context dependent rule of thumb: if it has a parent allocate dynamically.

                        Eh! I hate allocating a single pointer on the heap, so as a consequence I hate that rule of thumb. Nothing personal, but it's just terribly inefficient, even if manually detaching the parent feels so clumsy.

                        Chris KawaC Offline
                        Chris KawaC Offline
                        Chris Kawa
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        @kshegunov Sure, if it's one. That's where the super * part of the rule comes in :)

                        Nothing personal, but it's just terribly inefficient

                        Agreed, but otherwise it's really fragile. Even if you have it perfectly under control and all 50 widgets in your dialog play nice there's always that intern that comes in and tries to be smart by rearranging your class members so the name alignment looks nicer :)

                        It's the usual design struggle - it depends on oh so many factors, not all technical.
                        But yeah, I'm usually the one complaining about performance, so I'd be a hypocrite not to agree ;)

                        kshegunovK 1 Reply Last reply
                        1
                        • Chris KawaC Chris Kawa

                          @kshegunov Sure, if it's one. That's where the super * part of the rule comes in :)

                          Nothing personal, but it's just terribly inefficient

                          Agreed, but otherwise it's really fragile. Even if you have it perfectly under control and all 50 widgets in your dialog play nice there's always that intern that comes in and tries to be smart by rearranging your class members so the name alignment looks nicer :)

                          It's the usual design struggle - it depends on oh so many factors, not all technical.
                          But yeah, I'm usually the one complaining about performance, so I'd be a hypocrite not to agree ;)

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by kshegunov
                          #12

                          @Chris-Kawa said in class pointer and non pointer member function question..:

                          Agreed, but otherwise it's really fragile.

                          Maybe. If I may suggest a better rule of thumb:
                          Use member variables (QObjects) and parent them to the containing one, like this:

                          class A : public QObject
                          {
                             QObject b, c;
                          
                             A(QObject * parent = nullptr)
                                 : QObject(parent), b(this), c(this)
                             {
                             }
                          };
                          

                          PS. Don't get me wrong, the pain is real. Currently I'm tinkering with Qt3D and QML. Everybody and their mother is a QObject there. Need a struct with 3 plain members for configuration, take this QObject on the heap instead ...

                          Read and abide by the Qt Code of Conduct

                          Chris KawaC 1 Reply Last reply
                          1
                          • kshegunovK kshegunov

                            @Chris-Kawa said in class pointer and non pointer member function question..:

                            Agreed, but otherwise it's really fragile.

                            Maybe. If I may suggest a better rule of thumb:
                            Use member variables (QObjects) and parent them to the containing one, like this:

                            class A : public QObject
                            {
                               QObject b, c;
                            
                               A(QObject * parent = nullptr)
                                   : QObject(parent), b(this), c(this)
                               {
                               }
                            };
                            

                            PS. Don't get me wrong, the pain is real. Currently I'm tinkering with Qt3D and QML. Everybody and their mother is a QObject there. Need a struct with 3 plain members for configuration, take this QObject on the heap instead ...

                            Chris KawaC Offline
                            Chris KawaC Offline
                            Chris Kawa
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            @kshegunov said:

                            Use member variables (QObjects) and parent them to the containing one, like this:

                            Yeah, kinda, but it's hairy with widgets. Often you have a class with bunch of members that parent each other through layouts, menus, views and what not.

                            I'm tinkering with Qt3D and QML. Everybody and their mother is a QObject there

                            Sigh, I feel you. I mean... that's one of the reasons that, although I'm all about graphics, I've never even tried Qt3D. I just can't see how this could ever have any reasonable performance for complexity beyond maybe a car dashboard. QObject is fat and it was designed back in the day as a building block for widgets based static ui interfaces. If I had to have an overhead of a QObject for every mesh, texture or a friggin buffer attribute I would need 128GB of RAM and a beefy top shelve GPU to even start.

                            And don't even get me started on QML :P Maybe I'm getting old but I feel very left behind with Qt 6.

                            kshegunovK 1 Reply Last reply
                            1
                            • Chris KawaC Chris Kawa

                              @kshegunov said:

                              Use member variables (QObjects) and parent them to the containing one, like this:

                              Yeah, kinda, but it's hairy with widgets. Often you have a class with bunch of members that parent each other through layouts, menus, views and what not.

                              I'm tinkering with Qt3D and QML. Everybody and their mother is a QObject there

                              Sigh, I feel you. I mean... that's one of the reasons that, although I'm all about graphics, I've never even tried Qt3D. I just can't see how this could ever have any reasonable performance for complexity beyond maybe a car dashboard. QObject is fat and it was designed back in the day as a building block for widgets based static ui interfaces. If I had to have an overhead of a QObject for every mesh, texture or a friggin buffer attribute I would need 128GB of RAM and a beefy top shelve GPU to even start.

                              And don't even get me started on QML :P Maybe I'm getting old but I feel very left behind with Qt 6.

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by
                              #14

                              @Chris-Kawa said in class pointer and non pointer member function question..:

                              Yeah, kinda, but it's hairy with widgets. Often you have a class with bunch of members that parent each other through layouts, menus, views and what not.

                              That is fair. When they're on the same hierarchy it's useful to declare the ownership explicitly through the constructor. Even if reparenting happens down the tree this ensures that the parent always outlives the child and you don't double-axe the object. Something like this:

                              QDialog someDialog;
                              QAction action(&someDialog);
                              // More children here, so we ensure the children are destroyed before the ancestor ...
                              

                              Sigh, I feel you. I mean... that's one of the reasons that, although I'm all about graphics, I've never even tried Qt3D. I just can't see how this could ever have any reasonable performance for complexity beyond maybe a car dashboard. QObject is fat and it was designed back in the day as a building block for widgets based static ui interfaces. If I had to have an overhead of a QObject for every mesh, texture or a friggin buffer attribute I would need 128GB of RAM and a beefy top shelve GPU to even start.

                              For a thousand meshes with 6 vertices and normals each with a simple phong material I got 20-30 fps for my RX580, so don't hold your breath (not going to even mention the load times ...). But honestly I'm not entirely convinced it's the Qt3D itself, more like the default QML integration. The damn thing renders the scene on a texture which it blits after than onto the QML scene. And to be honest I'm rather annoyed by the lack of any reasonable documentation or an example how one integrates the two in a fashion beyond the proof-of-concept level. It all feels like stitched with white thread ... I'm left with reading sources for few days now, which is beyond ridiculous ...

                              And don't even get me started on QML :P Maybe I'm getting old but I feel very left behind with Qt 6.

                              Nah. It's the same as the widgets underneath. You can even build it directly from C++ if you don't mind the verbosity. Thankfully the QtQuick scenegraph has nothing to do with the QML itself, the latter being just a glorified factory for the QQuickItems.

                              Read and abide by the Qt Code of Conduct

                              Chris KawaC 1 Reply Last reply
                              0
                              • kshegunovK kshegunov

                                @Chris-Kawa said in class pointer and non pointer member function question..:

                                Yeah, kinda, but it's hairy with widgets. Often you have a class with bunch of members that parent each other through layouts, menus, views and what not.

                                That is fair. When they're on the same hierarchy it's useful to declare the ownership explicitly through the constructor. Even if reparenting happens down the tree this ensures that the parent always outlives the child and you don't double-axe the object. Something like this:

                                QDialog someDialog;
                                QAction action(&someDialog);
                                // More children here, so we ensure the children are destroyed before the ancestor ...
                                

                                Sigh, I feel you. I mean... that's one of the reasons that, although I'm all about graphics, I've never even tried Qt3D. I just can't see how this could ever have any reasonable performance for complexity beyond maybe a car dashboard. QObject is fat and it was designed back in the day as a building block for widgets based static ui interfaces. If I had to have an overhead of a QObject for every mesh, texture or a friggin buffer attribute I would need 128GB of RAM and a beefy top shelve GPU to even start.

                                For a thousand meshes with 6 vertices and normals each with a simple phong material I got 20-30 fps for my RX580, so don't hold your breath (not going to even mention the load times ...). But honestly I'm not entirely convinced it's the Qt3D itself, more like the default QML integration. The damn thing renders the scene on a texture which it blits after than onto the QML scene. And to be honest I'm rather annoyed by the lack of any reasonable documentation or an example how one integrates the two in a fashion beyond the proof-of-concept level. It all feels like stitched with white thread ... I'm left with reading sources for few days now, which is beyond ridiculous ...

                                And don't even get me started on QML :P Maybe I'm getting old but I feel very left behind with Qt 6.

                                Nah. It's the same as the widgets underneath. You can even build it directly from C++ if you don't mind the verbosity. Thankfully the QtQuick scenegraph has nothing to do with the QML itself, the latter being just a glorified factory for the QQuickItems.

                                Chris KawaC Offline
                                Chris KawaC Offline
                                Chris Kawa
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                @kshegunov said:

                                For a thousand meshes with 6 vertices and normals each with a simple phong material I got 20-30 fps for my RX580

                                In the meantime I'm staring at a blinking red counter showing ~16'000 render items, each consisting of a vertex and index buffer of few thousands elements, with multi layer materials and heavy post process pipeline and scratching my head how to fit it in 16ms on an 8 year old console hardware :P Nope, Qt3D is definitely not for me.

                                kshegunovK 1 Reply Last reply
                                0
                                • Chris KawaC Chris Kawa

                                  @kshegunov said:

                                  For a thousand meshes with 6 vertices and normals each with a simple phong material I got 20-30 fps for my RX580

                                  In the meantime I'm staring at a blinking red counter showing ~16'000 render items, each consisting of a vertex and index buffer of few thousands elements, with multi layer materials and heavy post process pipeline and scratching my head how to fit it in 16ms on an 8 year old console hardware :P Nope, Qt3D is definitely not for me.

                                  kshegunovK Offline
                                  kshegunovK Offline
                                  kshegunov
                                  Moderators
                                  wrote on last edited by
                                  #16

                                  @Chris-Kawa said in class pointer and non pointer member function question..:

                                  ... scratching my head how to fit it in 16ms on an 8 year old console hardware :P Nope, Qt3D is definitely not for me.

                                  You have to give me some hints about the engine(s) you use when I'm ready to give up on the Qt3D. ;)

                                  Read and abide by the Qt Code of Conduct

                                  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