When using a Qt container as Qlist, Qvector etc to hold some class (say a complex class with many data members and logics) and calling insert/append/push_back will the object added to the container be inserted to the container or it will be copied (cctor) ?
Suppose it is copied then If I dynamically allocate it and pass a pointer then only the pointer will be copied? And if I pass the object itself then I need to free the memory I've allocated before because the object is copied ?
I could some official documentation so I'm asking here...
Thanks
In the case of QObject derived objects, you have to use dynamic allocation and just put pointers in the container, because such objects have unique identities and as such are prohibited from copying. In that case only the pointer is copied around, which is just an integer, the copying of which has no effect on the actual object it points to. With dynamically allocated objects you have to either manage lifetime manually or use Qt's parent/child functionality to have objects "collected" by their parent objects.
The values stored in the various containers can be of any assignable data type. To qualify, a type must provide a default constructor, a
copy constructor, and an assignment operator. This covers most data
types you are likely to want to store in a container, including basic
types such as int and double, pointer types, and Qt data types such as
QString, QDate, and QTime, but it doesn't cover QObject or any QObject
subclass (QWidget, QDialog, QTimer, etc.). If you attempt to
instantiate a QList, the compiler will complain that
QWidget's copy constructor and assignment operators are disabled.
As the quoted text above indicates, when placing the actual instances in a container, copying of the object will occur. In this case you don't have to manually delete anything, since the source of the copy would typically be a local object and often a temporary, of which the compiler will take care.
"Placement new" is a C++ feature you can use to specify the place the object is constructed in memory, but it comes at complexity of managing it and some limitations. The advantages of placement new and memory pools rarely outweigh the increase of complexity and loss of flexibility.
Related
I have a C++ object pointer with many data members. I need them all available in QML. One obvious way would be to create a Q_PROPERTY for each member so they can be individually accessed via QML. However, if we are talking about dozens of data members, well that's a lot of lines of Q_PROPERTY, not to mention having to individually handle these in QML as separate properties as well (especially if dealing with "on changed" signals for each property).
I am wondering if it is possible to make a single Q_PROPERTY that would include all the data members I need. But what is not clear to me is the apparent mismatch between the types that QML supports and the types you can list in a Q_PROPERTY. For example, in QML, we have a basic string but its corresponding lising in a C++ Q_PROPERTY must be QString:
Q_PROPERTY(QString datastring READ showdata NOTIFY datastringChanged)
//in QML, `datastring` is just a plain string
Would there be more complex properties like lists or arrays that can be easily matched? QML has a list type and C++ has the QList but are these the same thing? Where can I find a listing of compatible types between C++ and QML?
On the other hand, having individual Q_PROPERTY for each data member could likely be better performance (my data is large and often changing) since the QML would not need to parse anything, perhaps.
Would there be more complex properties like lists or arrays that can
be easily matched? QML has a list type and C++ has the QList but are
these the same thing? Where can I find a listing of compatible types
between C++ and QML?
Have a look at the C++/JS data conversion help page. I think the list missed that QList<QObject*> is also possible.
On the other hand, having individual Q_PROPERTY for each data member
could likely be better performance (my data is large and often
changing) since the QML would not need to parse anything, perhaps.
Maybe, yes, depends on your performance needs. A C++ QList gets converted to a JavaScript list when accessed from QML/JS. That's a bit of conversion overhead indeed. Also, ff an item in the list changes, you need to emit the notify signal for the complete property, and every JS binding in which the list was used needs to be reevaluated, which will again be many list conversions. That could be better by having more fine-grained properties, but it really depends.
Btw, with Qt 5.1 there now is MEMBER, which makes writing Q_PROPERTYs a bit easier.
Coming from the Symbian world, I'm used to using the heap as much as possible to avoid running out of stack space, especially when handling descriptors. CBase derived classes were always dynamically allocated on the heap, since if they were not, their member variables would stay uninitialized. Does the same convention apply to QObject-derived classes?
In Qt it seems to be common to put, for example QString, on the stack. Are the string contents put on the heap while QString acts as a container on the stack, or is everything put on the stack?
As sje397 said: It's idiomatic to put QString and containers on the stack, as they are implicitly shared. Their internals (pimpl idiom "d" pointer) are created on the heap. There is no point in creating the object itself on the heap, too. Just causes memory-management hassles and you lose the intended copy-on-write properties when passing pointers to strings/containers around.
QObjects on the other hand you want to create on the heap in almost all cases, as otherwise they would be destructed again right away. They can't be copied or assigned (well, one can enforce it for own subclasses, but the QObject semantics are broken then), and usually they are supposed to survive the method body they are created in.
Exception is QDialog, which is often created on the stack, followed by QDialog::exec, which blocks until the dialog is closed. But even that is strictly spoken unsafe, as external events (RPC calls, background operations) could cause the dialog to be deleted by its parent (if the parent itself is deleted) before exec returns.
Then having the dialog created on the stack will cause double deletion when unwinding the stack -> crash.
QString, and many other Qt classes, use implicit data sharing. That implies that memory is generally allocated on the heap.
I'm fairly new to C so be gentle.
I want to use the library interception method for Linux to replace calls to the OpenCL library with my own library. I understand that this can be done using LD_PRELOAD. So I can just re-implement the OpenCL functions as defined in the OpenCL header file within my own library which can then be linked against.
The problem is that this OpenCL header also contains some extern struct definitions, e.g.
typedef struct _cl_mem * cl_mem;
which are not defined within the OpenCL header. Is it possible these structs are defined within the OpenCL shared lib? If not, where might they be defined?
Cheers
Chris
That typedef declares a type pointing to a struct, the contents of which are undeclared. This means code using it can't do things like checking its size, copying the struct, or inspecting its contents - it simply has no idea what size it is.
This is a traditional technique in C to create an opaque, or private, type. You can declare the struct inside your OpenCL library, and the official header puts no restrictions on what that struct contains. It could even be empty, if all you need is an ID you can store in the pointer itself, though this is rarely done.
An example of the same technique used in the standard C library is the FILE type. It might be as simple as an integer file descriptor, or as complex as a struct containing the entire filesystem state; standard C code won't know. The particulars are known to the library only.
In short, you can declare that struct however you like - as long as you implement every function that handles that struct. The program that links to your library never handles the struct, only pointers to it.
To get a list of all the QWidgets created in an application we can simply call QApplication::allWidgets().
I've read the documentation, and I haven't found anything like this to get a list of all QObjects. If an application creates stand-alone QObjects that are not QWidgets I have no such function to use.
Is there a method to obtain such a list?
To begin with it's important to understand the difference between the QObject and QWidget classes.
class QObject
QObject instances have a pointer to their parent which may or may not be a null pointer. It's quite legitimate to create a QObject instance without a parent so long as you understand that it is your responsibility for that instance's lifetime i.e. if you don't delete it you will leak memory.
class QWidget
Although it appears you can create a QWidget without a parent, you can't. When you create an instance of a QWidget "without a parent" (i.e. by supplying a null pointer or letting it default to a null pointer) it's parent effectively gets set to your application's QApplication1 instance.
Is there a method to obtain such a list?
No. The reason QApplication::allWidgets() works is due to the fact that all QWidget instances have a pointer to them which is stored in your single QApplication instance. There is no central store of QObject pointers and therefore no in-built way of retrieving them.
One way around this is to ensure yourself that all QObjects instances (or instances of classes which inherit QObject) have a valid parent. Then you can use the QObject functions children(), findChild() and findChildren() to get pointers to these objects.
These are powerful tools, and like anything powerful, use them with care! Make sure you understand C++ object life spans before you use these in production code.
Notes:
QApplication inherits from QCoreApplication which inherits from QObject. There are some restrictions placed on how QApplication is used by the Qt framework.
I am getting confused about the QList copy constructor by the documentation.
QList::QList ( const QList & other )
Constructs a copy of other.
This operation takes constant time,
because QList is implicitly shared.
This makes returning a QList from a
function very fast. If a shared
instance is modified, it will be
copied (copy-on-write), and that takes
linear time.
Then on the link about being implicitly shared, it talks about reference counting and copy-on-write. Is this a deep copy or just a shallow copy?
It's a shallow copy. A deep copy of the data happens behind the scenes the first time you call a non-const function on the copy or the original list.
This operation takes constant time,
because QList is implicitly shared.
If you don't modify the list, those are shared ! So Behind the scene, you read at the same address the informations !
If a shared instance is modified, it
will be copied (copy-on-write), and
that takes linear time.
But if you modify the copy list, there is no other choice that copy effectively the list ! And so, you have a linear cost depending on the list size.
from qt doc on copy on write and shared memory :
A deep copy implies duplicating an
object. A shallow copy is a reference
copy, i.e. just a pointer to a shared
data block. Making a deep copy can be
expensive in terms of memory and CPU.
Making a shallow copy is very fast,
because it only involves setting a
pointer and incrementing the reference
count.
So if you don't modify the list you read the information at the same address that the list given as parameter, it's called shallow copy. And if you modify it, you will have a deep copy of the list.
The copy constructor does a fast (shallow) copy. If you then modify either the original list, or it's copy, a deep copy of the data will be made.
If you're in any doubt, I suggest you re-read the documetnation on copy-on-write semantics.
This is the same behaviour as QString, QList, QArray, and many other Qt classes.
AFAIK, when copying the content (on write), it calls the copy constructor of each element in the list, like in the case of std::list.