2

The question is as in the title.

For example:

QPropertyAnimation *animation;
animation = new QPropertyAnimation(this, "windowOpacity", this);

or

QPropertyAnimation animation;
animation.setTargetObject(this);
animation.setPropertyName("windowOpacity");
animation.setParent(this);

Which is more efficient?

edit: though it has no significant difference unless done repeatedly, i would still like to know, i would rather want answers than opinions -as stackoverflow's guidelines suggest.

kien bui
  • 1,760
  • 2
  • 17
  • 33
Subaru Tashiro
  • 2,166
  • 1
  • 14
  • 29
  • 5
    A better question: Does it matter? If your program spends most of its time creating widgets then you have a design issue. –  Dec 18 '11 at 01:28
  • 1
    The first should be more efficient if by efficient you mean speed. – Arlen Dec 18 '11 at 01:29
  • 1
    What kind of efficiencies are you looking for here? It would be less code to type, and also less error prone to initialise mandatory properties in a constructor. – clstrfsck Dec 18 '11 at 01:32
  • @Arlen, ignoring the fact that i gave a bad example, (the first one allocating from heap), if ever both were allocated on stack, why would the first one be faster? – Subaru Tashiro Dec 18 '11 at 02:01
  • @msandiford i mean efficient in practice, considering everything. i know the question is ambiguous, but you may suggest anything. – Subaru Tashiro Dec 18 '11 at 02:03
  • PS: All you'll ever get is opinion. It's just that some is more informed than others. – Hot Licks Dec 18 '11 at 02:50

4 Answers4

6

First, why new in the first example? I'll assume that you will create both variables on the same storage (heap / stack).

Second, this isn't a matter of Qt, it applies to C++ in general.

Without any prior knowledge about the class you are creating, you can be sure of one thing: The constructor with arguments version is at least as efficient as the setter version.

This is because, in the worst case, the constructor might look like this:

QPropertyAnimation(QObject* target, const QByteArray & prop_name, QObject* parent = 0)
{
  // members are default initializer, now explicitly set
  this->setTargetObject(target);
  this->setPropertyName(prop_name);
  this->setParent(parent)
}

However, any person that has atleast worked through a good book will write the constructor like this:

QPropertyAnimation(QObject* target, const QByteArray & prop_name, QObject* parent = 0)
  : m_target(target)
  , m_prop_name(prop_name)
  , m_parent(parent)
{
  // members explicitly initialized
}
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • i see, no difference then. i did give a bad example, and you assumed correct. thank you for your answer. – Subaru Tashiro Dec 18 '11 at 01:58
  • @Subaru: There is a difference - that the constructor version is *at least* as fast. In practise that means, that the ctor *will* be faster. And if not, you didn't lose anything but got clarity and conciseness from the constructor syntax. – Xeo Dec 18 '11 at 02:07
  • hmm... good point, "at least as fast, if not faster". Got it. plus it's more readable, which does also answer some of my concerns about doing so in practice. thank you. i would vote this up if i could. – Subaru Tashiro Dec 18 '11 at 02:14
  • I have more to ask, and i do apologize if it sounds stupid. In class variable declarations, you cannot call constructors, you can only do forward declarations, so i have two choices; i would have to resort to allocating in heap if i want to use the constructor that sets values as arguments, or allocate in stack and do multiple function calls. What do you say of this? – Subaru Tashiro Dec 18 '11 at 16:20
  • @Subaru: You seriously need to grap a [good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). :) You can call constructors, it's exactly what the second version does (that weird colon-list before the body of the constructor). – Xeo Dec 18 '11 at 16:26
  • Ah! i get it. thanks. I don't have money to buy books though, or money to go to school for that matter. – Subaru Tashiro Dec 18 '11 at 16:35
  • @Subaru: If you seriously want to learn C++, *get* a book, no matter what it takes. Learning it without one is a trip down to hell and back. And down again. – Xeo Dec 18 '11 at 16:39
  • thank you, i will try my best. but maybe e-books will do for now. – Subaru Tashiro Dec 18 '11 at 17:01
1

At to whether the one call or three (OK, 2.5, since the first call is implicit) is "better" (ignoring the heap issue), it's worthwhile thinking about the conceptual flow of the program, and your intellectual control over it. And it's also worth considering practical issues related to coding.

On the caller side, if all the appropriate parameters are already at hand where the object is being created, then the single call makes it more obvious that, indeed, all the parameters "belong" to that object, and it's being created "in one piece". On the other hand, if using a single call means that the calling code must gather up parameters over time and then spit out a single "pent up" call, then it may be a better choice to create the object and then set the corresponding properties one at a time, as their values are developed.

And, on the callee side, there may be practical considerations. For instance, it may be that there are a dozen properties, with different uses of the object likely to use different combinations. Rather than provide dozens of different constructors, providing a single constructor (or a small number of them) combined with multiple property setters is both more efficient of programmer time and less apt to be confusing to the user of the object. But if the same combination of a relatively small number of parameters is (almost) always used then the single call is probably a better use of programmer resources.

(Of some importance here is the fact that C++ does not implement true keyword parameters, so when parameter lists get beyond 4-5 items one loses intellectual control over which parameter is which, especially if there are several forms of the constructor. In such a case using separate property setters gives the (rough) effect of keyword parameters and reduces the chance of confusion.)

Efficiency isn't always about CPU cycles. Efficient use of programmer time (including reduced time spent debugging) is, in many ways, far more important.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
  • i see, you just covered the parts everyone else did not consider, efficiency in development or practical use. so considering that, in summary, efficiency can also depend on how these functions and constructors are used. But i have more to ask, and i do apologize if it sounds stupid; in class variable declarations, you cannot call constructors, you can only do forward declarations, so i have two choices; i would have to resort to allocating in heap if i want to use the constructor that sets values as arguments, or allocate in stack and do multiple function calls. What do you say of this? – Subaru Tashiro Dec 18 '11 at 16:16
0

All else being equal one function call is better than 3.

Duck
  • 26,924
  • 5
  • 64
  • 92
0

You're comparing apples and oranges. In the first case you're constructing an object from heap, while in the second case you're constructing an object "in place", in another object or in automatic storage, so there's no heap overhead. Has nothing to do with whether you use a single constructor call or a (implicit) constructor plus two setters.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
  • Regardless of storage, a constructor can still be viewed as a method call. Normal calling conventions still apply. And when you come down to the instruction level, it's marginally more efficient to call one function than 3 (but so negligible it shouldn't matter). And as pointed out below, inlining by the compiler makes the difference pretty much nil. – Chris Eberle Dec 18 '11 at 01:42
  • i see, yours and @Chris' answers were the best so far, also, i now realize i gave a bad example since the first allocates from heap, but if ever it didn't, i do get both your point. – Subaru Tashiro Dec 18 '11 at 01:57
  • @chris -- I said nothing about one call vs 3. Clearly, in most cases the single call will be cheaper (if inlining doesn't negate the whole issue). But the heap allocation will generally swamp everything else. – Hot Licks Dec 18 '11 at 02:48
  • @HotLicks the heap isn't really that big of an issue. Malloc and new keep their own memory pool around, and if a request is small enough there's zero overhead. Since the object described above *can* fit onto the stack (which has space limits), it's probably safe to assume that it's a rather small footprint. Thus the chance that the program will make more than one request to the kernel for additional heap space is very low. So it's kind of a moot point. Then it really is about the calls. – Chris Eberle Dec 18 '11 at 03:38
  • @Chris -- I've written actual real live heap managers for commercial systems. The malloc/free cycle is, at minimum, about 10x a normal call overhead. – Hot Licks Dec 18 '11 at 04:36