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 7 Jun 2016, 16:21 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?

    K 1 Reply Last reply 7 Jun 2016, 16:23
    1
    • ? A Former User
      7 Jun 2016, 16:21

      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?

      K Offline
      K Offline
      kshegunov
      Moderators
      wrote on 7 Jun 2016, 16:23 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 7 Jun 2016, 16:29
      1
      • K kshegunov
        7 Jun 2016, 16:23

        @Wieland

        #include "ui_mainwindow.h"
        

        in the header, not only in source?
        :)

        ? Offline
        ? Offline
        A Former User
        wrote on 7 Jun 2016, 16:29 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.

        K 1 Reply Last reply 7 Jun 2016, 16:33
        0
        • ? A Former User
          7 Jun 2016, 16:29

          @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.

          K Offline
          K Offline
          kshegunov
          Moderators
          wrote on 7 Jun 2016, 16:33 last edited by kshegunov 6 Jul 2016, 16:33
          #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 7 Jun 2016, 16:39
          4
          • K kshegunov
            7 Jun 2016, 16:33

            @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 7 Jun 2016, 16:39 last edited by
            #5

            @kshegunov Ah.. sounds logical. Thank you!

            K 1 Reply Last reply 7 Jun 2016, 16:47
            0
            • ? A Former User
              7 Jun 2016, 16:39

              @kshegunov Ah.. sounds logical. Thank you!

              K Offline
              K Offline
              kshegunov
              Moderators
              wrote on 7 Jun 2016, 16:47 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 21 Jun 2016, 16:09 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