General question about Qt class conventions
-
Perhaps this is a deficiency in my C++ education/knowledge or in my simply keeping up with advances in C++ conventions but I have noticed something odd about Qt classes which makes me wonder about their use.
Qt seems to have classes that act more like typedefs, references, or structs. For example QChar. When I mouseover QChar it says it is a class. Yet I have noticed that you can use QChar just like a C++ char or wchar_t. When I look up documentation, regarding the class it says it is treated as an unsigned short. How is that possible when according to the mouse-over feedback it is not a struct (or typedef) but a class? Is there some sort of way to do this?
This also calls into question (at least for me) memory AND time management. Are QChar's persistent if they are declared in a method without using a pointer (because they are copied directly from one variable to another)? When I learned C++, I came to understand that instances of classes which were are NOT pointers allocated with the new keyword were created on the stack and then destroyed (reallocated) when the method was exited. This is one reason why pointers and references were necessary to begin with (aside from the other advantages they bring).
Yet in Qt, raw objects (instances) being returned from a method are common. It makes sense if these methods are accessors returning instances stored in the class being called but it seems to happen more often than that. Especially with classes like QString and QChar.
And what about the time it takes to load all that data on the stack? I always thought that when a raw class is put on the stack (rather than a pointer or reference), all data within the instance needs to be added to the stack (as it does when a struct is put on the stack). If the class is a list or something.... that is a LOT of time being consumed.
Perhaps my understanding is flawed or out of date. Either way, could someone clarify what is going on or at least point me to a resource where I can learn?
Thanks!
-
Hi,
A class that is put on the stack isi added to the stack, that is correct so far. But what does "add a class to the stack" mean? It means, all it's members are put on the stack.
- In case of a QChar (which only has an unsigned short), this is just 2 bytes.
- In case of a QList, this is
@union { QListData p; QListData::Data *d; };@
digging a bit deeped, "QListData p" just contains a pointer to dynamically allocated memory.
Qt has a lot of classes which are memory optimized (e.g. QString) and many of them implement the "copy on write" pattern. This means, they have a pointer and a ref count and on write, they detach. Doing this, you can copy them cheaply around and do not care about the memory.
-
Hi,
The keyword here is: implicit sharing. You can find more information in "this":http://qt-project.org/doc/qt-5/implicit-sharing.html chapter of Qt's documentation.
-
Hi,
[quote]Qt seems to have classes that act more like typedefs, references, or structs.[/quote]
- In C++, classes and structs are essentially the same thing. The only difference is that struct members are public by default, while class members are private by default.
- Your list a bit strange; typedefs and references can't be compared with structs and classes. Please tell us: According to your understanding, what is a typedef and what is a reference?
[quote]When I mouseover QChar it says it is a class. Yet I have noticed that you can use QChar just like a C++ char or wchar_t. When I look up documentation, regarding the class it says it is treated as an unsigned short. How is that possible when according to the mouse-over feedback it is not a struct (or typedef) but a class? Is there some sort of way to do this?[/quote]
Have a look at the source code: http://code.woboq.org/qt5/qtbase/src/corelib/tools/qchar.h.htmlIf you remove all the enums and class methods, you'll see that QChar contains only 1 member variable:
@
class QChar {
ushort ucs;
}
@Thus, each QChar object occupies the same amount of memory as an unsigned short (2 bytes). For comparison, an int occupies 4 bytes.
Anyway, Qt has 2 broad categories of datatypes: Value types and Identity types. See "this article":http://qt-project.org/doc/qt-5/object.html#qt-objects-identity-vs-value for details. Basically, identity types cannot be copied, and are passed around by pointers. On the other hand, value types can be copied, and they are passed around by value or by const reference.
As Gerolf and SGaist have pointed out, it is cheap to copy Qt objects because of implicit sharing. Nonetheless, passing values by const reference is even cheaper than copying them.
-
[quote author="JKSH" date="1408517682"]
- In C++, classes and structs are essentially the same thing. The only difference is that struct members are public by default, while class members are private by default.
- Your list a bit strange; typedefs and references can't be compared with structs and classes. Please tell us: According to your understanding, what is a typedef and what is a reference?
[/quote]
No not really... because I am speaking of behavior in memory. At least as far as I understand it, when a struct, typedef, or native type is returned from a method, the data is actually copied off the the stack into a local variable before the memory is reallocated where in a class it is not. At least that is the way things used to be... When I first learned C++ (I have used c# for a while)... the following method would NOT work...
@
MyClass returnLocalInstance()
{
MyClass localVariable(somedata);
// do something useful/important to class herereturn localVariable;
}
@And the calling code:
@MyClass var = returnLocalInstance();@
Trying to access the data in var (as returned from the above function) would result in either an error or bad data because the local variable has been reallocated. If I instead replaced 'MyClass with a struct, typedef, or a native type from the above function it would work fine because the data is copied in memory to the local variable before it is destroyed. When I was first learning C++ I learned the hard way that I had to use a pointer when I wanted to return a class instance that was created inside the method I called.
Yet this doesn't seem to be the case in Qt.
[quote author="JKSH" date="1408517682"]As Gerolf and SGaist have pointed out, it is cheap to copy Qt objects because of implicit sharing. Nonetheless, passing values by const reference is even cheaper than copying them.[/quote]
I will have to read the articles referred to for a more complete understanding but I think the ideas shared at least partially answer my question. Thanks.
-
[quote]
@
MyClass returnLocalInstance()
{
MyClass localVariable(somedata);
// do something useful/important to class herereturn localVariable;
}
@
[/quote]That code is valid C++, and it always has been. Like I said before, the memory allocated to a class is treated exactly the same way as the memory allocated to a struct.The idea that "structs are copied, classes are not" is invalid. Get rid of that idea from your mind, and things should become easier to understand.
All the best! Feel free to ask more questions if you have any.