0

Following up on this answer, I can declare the objects inside a Qt application as:

QLabel *label {new QLabel("bla")};

or

QLabel label {QLabel("bla")};

Let's assume that the app gets large enough; won't the stack risk getting too "crowded" with Qt objects (and the rest of the program) if I declare them as the 2nd way, even if it means it's faster? If so, how can I know when to avoid the 1st method over the 2nd?

a concerned citizen
  • 787
  • 2
  • 9
  • 25
  • 1
    It depends where `label` is actually. If it's in another object that is dynamically allocated with `new` then it won't be on the stack. – Some programmer dude Jan 09 '17 at 13:43
  • Well, yes, but then it doesn't matter that I declared it without `new`. I'm interested in the general case, how can someone know when (or why) to use `new` to avoid filling up the stack. Because, if the project starts small, and gets large, I doubt people will start counting objects and then re-translate them. Of course, I don't know for sure, that's why I asked. – a concerned citizen Jan 09 '17 at 13:48
  • 2
    As a general rule of thumb: Don't put large objects on the stack. And with many GUI toolkits it actually makes no sense having GUI-components stored as local variables anyway making the question kind of moot for this context. – Some programmer dude Jan 09 '17 at 13:51
  • I only have a few local (member) variables with which I am working on in other functions, but the whole GUI would have to have all the running objects put somewhere, no? That was my worry. But, following your answer, how can I know which objects are large and which are not? Are they covered in the manual? Or anywhere? – a concerned citizen Jan 09 '17 at 14:04

2 Answers2

2

You cannot get a definitive answer for "is it better to allocate on the heap or on the stack ?", which is the question you're asking.

Like said in the comments, large object should not be allocated on the stack but there is no clear limit and it would depend on many thing like the stack size or the hardware the program will be running on.

Also I'd like to note that if you can be sure that QLabel *label {new QLabel("bla")}; will be allocated on the heap (unless you reimplemented the new operator), you cannot say where QLabel label {QLabel("bla")} will be allocated.

Now you are talking about Qt. The way Qt and the QObject philosophy is designed, the syntax with pointers for QObject derived class would be preferred. But there are no rational argument against using the other form.

Also because Qt is using the d-pointer to hide its implementation details, QObject derived classes provided by Qt should not be extensively large.For instance even if you allocate a QLabel on the stack (24 bytes) most of its internals will be allocated on the heap (404 bytes).

Benjamin T
  • 8,120
  • 20
  • 37
1

The 2nd way you present won't work since QLabel is not copyable and thus the code won't compile. Perhaps you've meant

QLabel label{"bla"};

Furthermore, it has nothing to do with the stack at all. You could have written that line within a class:

class MyUi : public QWidget {
  QGridLayout m_layout{this};
  QLabel m_label{"bla"};
};

And, usually, you're supposed to do exactly that. You could of course allocate the widget as an automatic variable - usually this will only happen within main:

int main(int argc, char **argv) {
  QApplication app{argc, argv};
  ...
  MyUi ui;
  ui.show();
  return app.exec();
}

Here you need to use some common sense. How big will that class really get? Note that all Qt classes that derive from QObject use PIMPL and are either the size of a pointer, or the size of a couple of pointers - thus quite small.

In most cases, you shouldn't be worrying about it. If you run out of stack when your project gets truly huge, allocate MyUi dynamically and that's all:

int main(int argc, char **argv) {
  QApplication app{argc, argv};
  ...
  auto ui = std::make_unique<MyUi>();
  ui->show();
  return app.exec();
}

I've never ran into that problem personally: if your MyUi class is big enough, you've probably got serious issues with your design, and the class is way too monolithic and has too much responsibility.

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • I gave those `QLabel` examples out of my head, for exemplification (all are pointers in my small project, haven't even tried otherwise). With the current answers, I could go with normal value instantiations for my program, and with pointers for Qt. But there's what @someprogrammerdude said, about value objects that stem from pointer ones. It's really confusing for me. I don't use the `ui`, but if I declare the main window as `Win *w {new Win}` and the rest (inside my class) with normal value objects, will that create them in the heap and be faster (because it avoids `new` for the rest)? – a concerned citizen Jan 09 '17 at 16:50
  • First of all, don't do manual memory management. Use `std::make_unique` or `std::unique_ptr win{new Win}` if you have an older compiler. Secondly: yes, you should **always** hold object members by value if they have the same lifetime as the object. Where they will be created will depend on how you allocate the object instance. In your case, they will be literally within the dynamically allocated instance. – Kuba hasn't forgotten Monica Jan 09 '17 at 17:00
  • Finally, you're attacking a non-issue: anyone's reasonable guess should be that you won't run out of stack, and if you do, then your `Win` class is very badly broken. – Kuba hasn't forgotten Monica Jan 09 '17 at 17:00
  • More and more I think the same. I'll move all GUI related stuff onto the heap, and leave the stack for more sensible data, like plotting. I can have ~50k `double` points, which should be safe, but they could be reduced to `float`, for lesser cases. – a concerned citizen Jan 09 '17 at 17:06
  • You're doing it wrong. Very, badly, wrong. In modern C++ you should prefer to store things by value, and let the compiler figure everything else. – Kuba hasn't forgotten Monica Jan 09 '17 at 17:12
  • Then I won't use pointers at all. Will this affect the speed when accessing objects/variables? I am passing everywhere `const X &ref` or `X &ref` (unless it's a pointer). – a concerned citizen Jan 09 '17 at 17:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132724/discussion-between-a-concerned-citizen-and-kuba-ober). – a concerned citizen Jan 09 '17 at 19:35