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. C++11 default destructor and std::unique_ptr
QtWS25 Last Chance

C++11 default destructor and std::unique_ptr

Scheduled Pinned Locked Moved Solved General and Desktop
c++11uniqueptrdestructor
7 Posts 2 Posters 8.4k 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.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #1

    Hi!

    I'm playing around with C++11 features to improve my Qt programs which by now rely mostly on C++98.

    I have a QWidgets application with a QMainWindow derived MainWindow and a Ui::MainWindow generated with Qt Designer. Now I tried to be super smart and instead of keeping a pointer Ui::MainWindow *ui; I keep a std::unique_ptr to the ui. Thus I don't need the usual~MainWindow() with delete ui; inside anymore. This is what the code looks like:

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <memory>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
    
    private:
        std::unique_ptr<Ui::MainWindow> m_ui;
    };
    
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent)
        , m_ui(new Ui::MainWindow)
    {
        m_ui->setupUi(this);
    }
    

    That was my naive theory. Turns out it doesn't compile. The error says:

    /usr/include/c++/4.8/bits/unique_ptr.h:-1: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Ui::MainWindow]':
    
    /usr/include/c++/4.8/bits/unique_ptr.h:184: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Ui::MainWindow; _Dp = std::default_delete<Ui::MainWindow>]'
    
    /usr/include/c++/4.8/bits/unique_ptr.h:65: error: invalid application of 'sizeof' to incomplete type 'Ui::MainWindow'
      static_assert(sizeof(_Tp)>0,
                          ^
    

    I tried adding ~MainWindow() = default; but that didn't help. Can someone please explain to me what's going on here?

    kshegunovK 1 Reply Last reply
    1
    • ? A Former User

      Hi!

      I'm playing around with C++11 features to improve my Qt programs which by now rely mostly on C++98.

      I have a QWidgets application with a QMainWindow derived MainWindow and a Ui::MainWindow generated with Qt Designer. Now I tried to be super smart and instead of keeping a pointer Ui::MainWindow *ui; I keep a std::unique_ptr to the ui. Thus I don't need the usual~MainWindow() with delete ui; inside anymore. This is what the code looks like:

      mainwindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <memory>
      
      namespace Ui {
      class MainWindow;
      }
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit MainWindow(QWidget *parent = 0);
      
      private:
          std::unique_ptr<Ui::MainWindow> m_ui;
      };
      
      #endif // MAINWINDOW_H
      

      mainwindow.cpp

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent)
          , m_ui(new Ui::MainWindow)
      {
          m_ui->setupUi(this);
      }
      

      That was my naive theory. Turns out it doesn't compile. The error says:

      /usr/include/c++/4.8/bits/unique_ptr.h:-1: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Ui::MainWindow]':
      
      /usr/include/c++/4.8/bits/unique_ptr.h:184: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Ui::MainWindow; _Dp = std::default_delete<Ui::MainWindow>]'
      
      /usr/include/c++/4.8/bits/unique_ptr.h:65: error: invalid application of 'sizeof' to incomplete type 'Ui::MainWindow'
        static_assert(sizeof(_Tp)>0,
                            ^
      

      I tried adding ~MainWindow() = default; but that didn't help. Can someone please explain to me what's going on here?

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

      @Wieland

      #include "ui_mainwindow.h"
      

      in the header, not only in source?
      :)

      Read and abide by the Qt Code of Conduct

      ? 1 Reply Last reply
      1
      • kshegunovK kshegunov

        @Wieland

        #include "ui_mainwindow.h"
        

        in the header, not only in source?
        :)

        ? Offline
        ? Offline
        A Former User
        wrote on last edited by
        #3

        @kshegunov Hi! Before we move to the question why the forward declaration of Ui::MainWindow in the header might not be sufficient: Why doesn't the ~MainWindow() = default; work? Because, as soon as I add ~MainWindow(); to the header and MainWindow::~MainWindow() {} to the source it compiles.

        kshegunovK 1 Reply Last reply
        0
        • ? A Former User

          @kshegunov Hi! Before we move to the question why the forward declaration of Ui::MainWindow in the header might not be sufficient: Why doesn't the ~MainWindow() = default; work? Because, as soon as I add ~MainWindow(); to the header and MainWindow::~MainWindow() {} to the source it compiles.

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

          @Wieland
          Funny thing with templates. Instantiation happens where you do the specialization (in this case the header). The compiler needs the members to be fully defined to generate the default destructor (i.e. it needs to know the destructor of UI::MainWindow in this case and this is happening while parsing the header no less).

          When you provide your own destructor (in source) the compiler doesn't need to call the destructor of the unique_ptr class (thus the destructor of the Ui::MainWindow class) and you're fine only using forward declarations :)

          I hope I explained it understandably.

          :)

          Read and abide by the Qt Code of Conduct

          ? 1 Reply Last reply
          4
          • kshegunovK kshegunov

            @Wieland
            Funny thing with templates. Instantiation happens where you do the specialization (in this case the header). The compiler needs the members to be fully defined to generate the default destructor (i.e. it needs to know the destructor of UI::MainWindow in this case and this is happening while parsing the header no less).

            When you provide your own destructor (in source) the compiler doesn't need to call the destructor of the unique_ptr class (thus the destructor of the Ui::MainWindow class) and you're fine only using forward declarations :)

            I hope I explained it understandably.

            :)

            ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #5

            @kshegunov Ah.. sounds logical. Thank you!

            kshegunovK 1 Reply Last reply
            0
            • ? A Former User

              @kshegunov Ah.. sounds logical. Thank you!

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

              @Wieland
              My pleasure! :D

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • ? Offline
                ? Offline
                A Former User
                wrote on last edited by
                #7

                If someone needs a comprehensive 8 pages long explanation for what's exactly happening here, I recommend reading "Item 22: When using the Pimpl Idiom, define special member functions in the implementation file" from "Effective Modern C++" by Scott Meyers.

                1 Reply Last reply
                3

                • Login

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