Qt-interest Archive, July 2007
A basic question about QList
Message 1 in thread
I could not find anything in the documentation to clarify this for
me, so I am asking here. Forgive me if this sounds like a n00b
question :)
I'm making a QList of QPictures to do some multi-page graphics.
Will I make the compiler scream if I do this:
MyClass::method ( args )
{
...
QPicture picture ;
QPainter painter;
QList<QPicture> pictureList ;
for ( int loop = 0 ; loop < limit ; loop++ )
{
painter.begin(&picture);
... draw...
painter.end(&picture);
pictureList.append ( picture ) ;
}
}
Or do I need to do it this way:
MyClass::method ( args )
{
...
QPicture *picture ;
QPainter painter;
QList<QPicture *> pictureList ;
for ( int loop = 0 ; loop < limit ; loop++ )
{ picture = new QPicture() ;
painter.begin(picture);
... draw...
painter.end(picture);
pictureList.append ( picture ) ;
}
}
My gut feeling says that the second way is the proper way, but I
cannot find proof.
Thanks.
--
[ signature omitted ]
Message 2 in thread
> I could not find anything in the documentation to clarify this for
> me, so I am asking here. Forgive me if this sounds like a n00b
> question :)
There are no such things as "n00b"-questions ;-)
[snip]
The first way you are showing is just fine :-) QList is a value based list
class. You can create your QPictures and insert it in the list. The copy
constructor will be called, but since QPicture is implicitly shared, this
is really fast. IMO the first way is the proper one since you do not have
to mess with pointers. A lot less chance to make mistakes I would think
;-)
Regards,
Malte
--
[ signature omitted ]
Message 3 in thread
On 7/4/07, Dan White <ygor@xxxxxxxxxxx> wrote:
> MyClass::method ( args )
> {
> ...
> QPicture picture ;
> QPainter painter;
>
> QList<QPicture> pictureList ;
>
>
> for ( int loop = 0 ; loop < limit ; loop++ )
> {
> painter.begin(&picture);
> ... draw...
> painter.end(&picture);
>
> pictureList.append ( picture ) ;
> }
> }
This seems ok, but I suggest moving QPicture object inside the loop, so
you will work on brand-new-clean-object and not dealing with possible state
problems.
Or do I need to do it this way:
>
> MyClass::method ( args )
> {
> ...
> QPicture *picture ;
> QPainter painter;
>
> QList<QPicture *> pictureList ;
>
>
> for ( int loop = 0 ; loop < limit ; loop++ )
> { picture = new QPicture() ;
>
> painter.begin(picture);
> ... draw...
> painter.end(picture);
>
> pictureList.append ( picture ) ;
> }
> }
This it valid as well, but it much less advisable to work with a raw
pointers, as it is always a source of problems and bugs. It is very
difficult to get a true exception-safety with pointers, you have always to
remember to delete them afterwards, they might be "null" at any place, etc.
Not worth dealing with, until you must. You could, of course work around by
using a smart pointer, that will take care of most of the problems, i.e.
like:
QList<shared_ptr<QPicture> > pictureList ;
but you just better end, using the first way, as behind the scenes QPicture
is basically does the very same thing - implicitly shared reference-counted
smart pointer.
And another thing - are you really sure you want a list? From my practice,
list is rarely an optimal container solution. It's storage model are far
from optimal (fragmented and with large overhead), the access are only
linear, etc. Almost the single benefit you get from using it - is a
constant-time insertion at the middle of the container. I would like to
advice you to consider QSet (std::set) - ensures uniqueness of element, fast
insertion, removal and lookup (log(n) or constant - depending if it is tree
or hash-based), QVector (std::vector) - most efficient storage and lookup,
but somewhat inefficient insertion (unless you know the size in advance, and
only insert elements at the end, which is seems to be your case), std::deque
- much like vector, but gives an efficient insertion and removal, from both
ends, and without reallocating whole contents (it works with vector-like
chunks internally).
--
[ signature omitted ]