Please nominate your Qt Champions for 2021!

QLabel on heap vs QLabel on stack

  • Hello,
    Why does the complier allow this:
    @QLabel *label = new QLabel("Hello World");@

    and not this:
    @QLabel label = QLabel("Hello World");@

    I get the error:
    @C:\Users\Blah\Blah - Basic Application and HTML Aware Widgets\Minimal\Main.cpp:10: error: C2248: 'QLabel::QLabel' : cannot access private member declared in class 'QLabel'@

    I know this might be more of a C++ question than a Qt question but I'm just wondering.

  • Well as you say, this is raw C++.

    The proper syntax for building objects on the stack would be
    QLabel label("Hello World");

    I suspect that there could be a syntactic ambiguity with a function call pattern...
    And I agree that the error message (VS, it seems) is really useless.


  • Moderators

    No, it is not useless. You just need to understand what is going on and then you'll see it tells you exactly what is wrong.

    The second syntax creates a temporary, unnamed QLabel instance and then tries to construct the "label" variable through its copy constructor ( QLabel::QLabel(const Qlabel&) ).

    Now, most widgets, including QLabel use Q_DISABLE_COPY() macro, which declares a private copy constructor and assignment operator. This is to disable copying widgets by value, which makes little sense when you think about layouts.

    So, to conclude - the compiler is saying exactly what is going on - you are trying to use a private member (the private copy constructor QLabel::QLabel) of the class QLabel. Don't do that.

  • It nos not just widgets, QObject and derived classes must not be copied, that is why the copy constructor and assignment operator for library classes are declared as private for C++98 compilers. In C++11 a more elegant approach is being used, instead of making the method private, it is marked as = delete.

    On a side note, you can declare class members as stack values and use the initializer list if you for some reason want to avoid dynamic memory allocating, which is the preferred way in Qt. Instead of using pointers and calling new in the constructor you can put UI sub-elements on the stack and save a tiny amount of resources. But since the API is written to accept pointers (precisely because QOBject derived do not have copy constructors and assignment operators), you must make extensive use of the & operator to get addresses instead of the instance.

  • Hello,
    Total brain fart I saw that:
    @QLabel ( const QString & text, QWidget * parent = 0, Qt::WindowFlags f = 0 )@

    and couldn't find a copy constructor on the QLabel Class Reference and assumed it was implicitly called. Thanks I'm just so used to never using dynamic memory where I have to remember to explicitly delete each instead of using a destructor, which I guess Qt does for you anyways.

  • QObject derived classes (should always) have their constructors declared explicit, precisely to avoid the otherwise numerous possible implicit conversions and potential problems.

    I myself think C++ is way too implicit and rarely rely on implicit conversions, just to make sure it is clear to anyone (including me) what actually happens.

Log in to reply