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. question about singletons
Forum Updated to NodeBB v4.3 + New Features

question about singletons

Scheduled Pinned Locked Moved Solved C++ Gurus
17 Posts 7 Posters 2.5k Views 4 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.
  • S Offline
    S Offline
    SimonSchroeder
    wrote on last edited by
    #8

    Well, if you really do want to use singletons, make sure to use a proper, thread-safe approach in C++. Namely, use a static variable inside a function:

    class MyClass
    {
      //...
      static MyClass &instance() { static MyClass object; return object; }
    };
    

    static variables inside a function are automatically thread-safe (since C++11). A class variable is not automatically thread-safe.

    The best explanation I have heard against using singletons is because of testing. There is a good talk about singletons and what to use instead: https://www.youtube.com/watch?v=K5c7uvWe_hw

    1 Reply Last reply
    1
    • J.HilkJ J.Hilk

      The others are of course right, but Singletons do have their applications, especially in Qt. As they are one of only 3(ish) ways to share/access data between/from QML and c++

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

      @J-Hilk said in question about singletons:

      The others are of course right, but Singletons do have their applications, especially in Qt. As they are one of only 3(ish) ways to share/access data between/from QML and c++

      QML singleton isn't the same as C++ singleton, and there are intricacies with that integration, true. However in the usual case the C++ object is managed by the QML engine, which will free it whenever it tears itself down, which is the correct way.

      @SimonSchroeder said in question about singletons:

      static variables inside a function are automatically thread-safe (since C++11). A class variable is not automatically thread-safe.

      No they aren't. Only the initialization is thread-safe, which is also guaranteed for any global static (scoped or not). This is not the main problem, though. You could've made the init thread safe manually, if necessary.

      @mzimmers said in question about singletons:

      Can you give me a brief explanation why singletons are to be avoided in this use case?

      Multiple reasons. For one they are evil coupling, way against OOP principles, where you want to decouple, not vice versa.
      Secondly, they have lifetime problems. If you do it on the heap (as you seem to have opted for) who cleans up after you're done? In Qt the QCoreApplication is already a singleton, why would you need more. You can attach any QObject to it at any time you want. Moreover, you shan't create any QObject before the QCoreApplication is live, so you're going to get into real trouble if you naively do:

      MyClassFromQObject m_instance;
      
      int main()
      {
          ....
      }
      

      This violates the API rules, and may/will crash cryptically, which is worse.

      Just do yourself a favor and don't do it!

      Read and abide by the Qt Code of Conduct

      J.HilkJ JonBJ S 3 Replies Last reply
      2
      • kshegunovK kshegunov

        @J-Hilk said in question about singletons:

        The others are of course right, but Singletons do have their applications, especially in Qt. As they are one of only 3(ish) ways to share/access data between/from QML and c++

        QML singleton isn't the same as C++ singleton, and there are intricacies with that integration, true. However in the usual case the C++ object is managed by the QML engine, which will free it whenever it tears itself down, which is the correct way.

        @SimonSchroeder said in question about singletons:

        static variables inside a function are automatically thread-safe (since C++11). A class variable is not automatically thread-safe.

        No they aren't. Only the initialization is thread-safe, which is also guaranteed for any global static (scoped or not). This is not the main problem, though. You could've made the init thread safe manually, if necessary.

        @mzimmers said in question about singletons:

        Can you give me a brief explanation why singletons are to be avoided in this use case?

        Multiple reasons. For one they are evil coupling, way against OOP principles, where you want to decouple, not vice versa.
        Secondly, they have lifetime problems. If you do it on the heap (as you seem to have opted for) who cleans up after you're done? In Qt the QCoreApplication is already a singleton, why would you need more. You can attach any QObject to it at any time you want. Moreover, you shan't create any QObject before the QCoreApplication is live, so you're going to get into real trouble if you naively do:

        MyClassFromQObject m_instance;
        
        int main()
        {
            ....
        }
        

        This violates the API rules, and may/will crash cryptically, which is worse.

        Just do yourself a favor and don't do it!

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #10

        @kshegunov said in question about singletons:

        QML singleton isn't the same as C++ singleton, and there are intricacies with that integration, true. However in the usual case the C++ object is managed by the QML engine, which will free it whenever it tears itself down, which is the correct way.

        I'm not talking about QML singletons

        I'm talking about this one:
        https://doc.qt.io/qt-6/qqmlengine.html#qmlRegisterSingletonInstance


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        kshegunovK 1 Reply Last reply
        0
        • J.HilkJ J.Hilk

          @kshegunov said in question about singletons:

          QML singleton isn't the same as C++ singleton, and there are intricacies with that integration, true. However in the usual case the C++ object is managed by the QML engine, which will free it whenever it tears itself down, which is the correct way.

          I'm not talking about QML singletons

          I'm talking about this one:
          https://doc.qt.io/qt-6/qqmlengine.html#qmlRegisterSingletonInstance

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

          @J-Hilk said in question about singletons:

          This is a QML singleton. Notice that you inject the object pointer to the QML engine. Your C++ object is created at runtime somewhere, presumably as a main() local or a child of some other QObject.

          Read and abide by the Qt Code of Conduct

          J.HilkJ 1 Reply Last reply
          0
          • kshegunovK kshegunov

            @J-Hilk said in question about singletons:

            This is a QML singleton. Notice that you inject the object pointer to the QML engine. Your C++ object is created at runtime somewhere, presumably as a main() local or a child of some other QObject.

            J.HilkJ Offline
            J.HilkJ Offline
            J.Hilk
            Moderators
            wrote on last edited by J.Hilk
            #12

            @kshegunov
            alt text

            but pre 5.14 you were required to pass on a function pointer, static getter, instead of the object pointer, IIRC


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            1 Reply Last reply
            0
            • kshegunovK kshegunov

              @J-Hilk said in question about singletons:

              The others are of course right, but Singletons do have their applications, especially in Qt. As they are one of only 3(ish) ways to share/access data between/from QML and c++

              QML singleton isn't the same as C++ singleton, and there are intricacies with that integration, true. However in the usual case the C++ object is managed by the QML engine, which will free it whenever it tears itself down, which is the correct way.

              @SimonSchroeder said in question about singletons:

              static variables inside a function are automatically thread-safe (since C++11). A class variable is not automatically thread-safe.

              No they aren't. Only the initialization is thread-safe, which is also guaranteed for any global static (scoped or not). This is not the main problem, though. You could've made the init thread safe manually, if necessary.

              @mzimmers said in question about singletons:

              Can you give me a brief explanation why singletons are to be avoided in this use case?

              Multiple reasons. For one they are evil coupling, way against OOP principles, where you want to decouple, not vice versa.
              Secondly, they have lifetime problems. If you do it on the heap (as you seem to have opted for) who cleans up after you're done? In Qt the QCoreApplication is already a singleton, why would you need more. You can attach any QObject to it at any time you want. Moreover, you shan't create any QObject before the QCoreApplication is live, so you're going to get into real trouble if you naively do:

              MyClassFromQObject m_instance;
              
              int main()
              {
                  ....
              }
              

              This violates the API rules, and may/will crash cryptically, which is worse.

              Just do yourself a favor and don't do it!

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

              @kshegunov said in question about singletons:

              In Qt the QCoreApplication is already a singleton, why would you need more

              This is the key point to me. "Singletons are evil", but why not hitch a ride on our application object and put everything you want into it? Then you don't create any singletons, but you still do singleton stuff even if you're not aware of it....

              kshegunovK 1 Reply Last reply
              0
              • JonBJ JonB

                @kshegunov said in question about singletons:

                In Qt the QCoreApplication is already a singleton, why would you need more

                This is the key point to me. "Singletons are evil", but why not hitch a ride on our application object and put everything you want into it? Then you don't create any singletons, but you still do singleton stuff even if you're not aware of it....

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

                @JonB said in question about singletons:

                This is the key point to me. "Singletons are evil", but why not hitch a ride on our application object and put everything you want into it?

                I didn't say to put anything into it. You should not derive from the application class without a very, very, very good reason.
                What you should do is compose the objects, where you can use the application object as root/parent.

                Then you don't create any singletons, but you still do singleton stuff even if you're not aware of it....

                The app object is a pseudo-singleton. It is accessible from everywhere, but it is created and initialized in main(), so it's not a global by itself. Only the reference to it is made global. Qt has its fair share of global variables, but they're not exposed explicitly to the user, with a good reason, they are a detail that shouldn't interest you.

                Read and abide by the Qt Code of Conduct

                JonBJ 1 Reply Last reply
                0
                • kshegunovK kshegunov

                  @JonB said in question about singletons:

                  This is the key point to me. "Singletons are evil", but why not hitch a ride on our application object and put everything you want into it?

                  I didn't say to put anything into it. You should not derive from the application class without a very, very, very good reason.
                  What you should do is compose the objects, where you can use the application object as root/parent.

                  Then you don't create any singletons, but you still do singleton stuff even if you're not aware of it....

                  The app object is a pseudo-singleton. It is accessible from everywhere, but it is created and initialized in main(), so it's not a global by itself. Only the reference to it is made global. Qt has its fair share of global variables, but they're not exposed explicitly to the user, with a good reason, they are a detail that shouldn't interest you.

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

                  @kshegunov said in question about singletons:

                  What you should do is compose the objects, where you can use the application object as root/parent.

                  ...and thereby take advantage of the "singleton-ness" without you craeting your own singleton... Maybe that's OK, I don't know. If you only add objects with application as parent I don't know how you access them.

                  The app object is a pseudo-singleton. It is accessible from everywhere, but it is created and initialized in main(), so it's not a global by itself. Only the reference to it is made global.

                  This is interesting. I'm not sure now what exactly it is that is objectionable/to be avoided in singletons. You still have the static QCoreApplication::instance() paradigm. You seem to be saying something about things are OK because it's created in main(), what you don't like is it being created outside main, or something?

                  I know it's a tricky area, but I don't think I'm the only one who does not understand what exactly is "bad" versus "ok" when people talk about don't use singletons.

                  While we are on this: the whole way Qt does QSqlDatabase::addDatabase(). Such that you can then access your database from anywhere. Somewhere along the line it must hold a single "list" of these (maybe it's private in the application object, I don't know). And that list is my idea of some kind of singleton.

                  kshegunovK 1 Reply Last reply
                  1
                  • JonBJ JonB

                    @kshegunov said in question about singletons:

                    What you should do is compose the objects, where you can use the application object as root/parent.

                    ...and thereby take advantage of the "singleton-ness" without you craeting your own singleton... Maybe that's OK, I don't know. If you only add objects with application as parent I don't know how you access them.

                    The app object is a pseudo-singleton. It is accessible from everywhere, but it is created and initialized in main(), so it's not a global by itself. Only the reference to it is made global.

                    This is interesting. I'm not sure now what exactly it is that is objectionable/to be avoided in singletons. You still have the static QCoreApplication::instance() paradigm. You seem to be saying something about things are OK because it's created in main(), what you don't like is it being created outside main, or something?

                    I know it's a tricky area, but I don't think I'm the only one who does not understand what exactly is "bad" versus "ok" when people talk about don't use singletons.

                    While we are on this: the whole way Qt does QSqlDatabase::addDatabase(). Such that you can then access your database from anywhere. Somewhere along the line it must hold a single "list" of these (maybe it's private in the application object, I don't know). And that list is my idea of some kind of singleton.

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

                    @JonB said in question about singletons:

                    ...and thereby take advantage of the "singleton-ness" without you craeting your own singleton... Maybe that's OK, I don't know. If you only add objects with application as parent I don't know how you access them.

                    You don't. Not directly anyway. You connect their signals and their slots and leave them in the wild. ;)

                    This is interesting. I'm not sure now what exactly it is that is objectionable/to be avoided in singletons. You still have the static QCoreApplication::instance() paradigm. You seem to be saying something about things are OK because it's created in main(), what you don't like is it being created outside main, or something?

                    It's marginally better if it's created in main(), because you guarantee the creation order (being explicit), which isn't true for simple globals. It's still coupling, but there's no one glove that fits all. A local static you could use to have init on use, but then you may run into trouble if it's accessed while global inits run (e.g. if the local static depends on a global static you're back in UB land).

                    I know it's a tricky area, but I don't think I'm the only one who does not understand what exactly is "bad" versus "ok" when people talk about don't use singletons.

                    The singleton is a glorified global variable, so if you're okay with having a thing in a global and bite the bullet, then you can use it. If there's a better way than having a global variable (which is 99% of cases), then don't use it. It is that simple.

                    While we are on this: the whole way Qt does QSqlDatabase::addDatabase(). Such that you can then access your database from anywhere. Somewhere along the line it must hold a single "list" of these (maybe it's private in the application object, I don't know). And that list is my idea of some kind of singleton.

                    It's a global variable (a hash map) that's buried within the implementation. The interface to access it however does more than just return a reference to it - it makes sure that you can call it safely from different threads for example.

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    3
                    • mzimmersM mzimmers has marked this topic as solved on
                    • kshegunovK kshegunov

                      @J-Hilk said in question about singletons:

                      The others are of course right, but Singletons do have their applications, especially in Qt. As they are one of only 3(ish) ways to share/access data between/from QML and c++

                      QML singleton isn't the same as C++ singleton, and there are intricacies with that integration, true. However in the usual case the C++ object is managed by the QML engine, which will free it whenever it tears itself down, which is the correct way.

                      @SimonSchroeder said in question about singletons:

                      static variables inside a function are automatically thread-safe (since C++11). A class variable is not automatically thread-safe.

                      No they aren't. Only the initialization is thread-safe, which is also guaranteed for any global static (scoped or not). This is not the main problem, though. You could've made the init thread safe manually, if necessary.

                      @mzimmers said in question about singletons:

                      Can you give me a brief explanation why singletons are to be avoided in this use case?

                      Multiple reasons. For one they are evil coupling, way against OOP principles, where you want to decouple, not vice versa.
                      Secondly, they have lifetime problems. If you do it on the heap (as you seem to have opted for) who cleans up after you're done? In Qt the QCoreApplication is already a singleton, why would you need more. You can attach any QObject to it at any time you want. Moreover, you shan't create any QObject before the QCoreApplication is live, so you're going to get into real trouble if you naively do:

                      MyClassFromQObject m_instance;
                      
                      int main()
                      {
                          ....
                      }
                      

                      This violates the API rules, and may/will crash cryptically, which is worse.

                      Just do yourself a favor and don't do it!

                      S Offline
                      S Offline
                      SimonSchroeder
                      wrote on last edited by
                      #17

                      @kshegunov said in question about singletons:

                      static variables inside a function are automatically thread-safe (since C++11). A class variable is not automatically thread-safe.

                      No they aren't. Only the initialization is thread-safe, which is also guaranteed for any global static (scoped or not).

                      Thank you for clarifying this. It is what I meant (but not what I wrote).

                      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