Qt-interest Archive, December 2006
C++ GUI Programming with Qt 4: pg 130
Pages: Prev | 1 | 2 | Next
Message 1 in thread
To a large extent, this is a C++ question not specific to Qt. But, given the
context in which it arose, it seems relevant to Qt. I understand that the
intent of the examples in _C++ GUI Programming with Qt 4_ are pedagogical and
therefore should stress clarity over optimal efficiency. Nonetheless, the
code shown on pg 130 gives me an opportunity to ask a question about coding
strategy in general.
Page 18 of _C++ Coding Standards_ by Sutter and Alexandrescu tells us "It is
not premature optimization to reduce spurious temporary copies of objects,
especially in inner loops, when doing so doesn't impact code complexity." My
question is whether any clock cycles might be saved by moving some of the
arithmetic out of the loops? What about calls to functions such as
settings.spanX()? If these values are unchanged during the loop, can
anything be gained by assigning them to a constant before entering the loop?
void Plotter::drawGrid(QPainter *painter)
{
QRect rect(Margin, Margin,
width() - 2 * Margin, height() - 2 * Margin);
if (!rect.isValid())
return;
PlotSettings settings = zoomStack[curZoom];
QPen quiteDark = palette().dark().color().light();
QPen light = palette().light().color();
for (int i = 0; i <= settings.numXTicks; ++i) {
int x = rect.left() + (i * (rect.width() - 1)
/ settings.numXTicks);
double label = settings.minX + (i * settings.spanX()
/ settings.numXTicks);
painter->setPen(quiteDark);
painter->drawLine(x, rect.top(), x, rect.bottom());
painter->setPen(light);
painter->drawLine(x, rect.bottom(), x, rect.bottom() + 5);
painter->drawText(x - 50, rect.bottom() + 5, 100, 15,
Qt::AlignHCenter | Qt::AlignTop,
QString::number(label));
}
//...
}
--
[ signature omitted ]
Message 2 in thread
In many cases those methods implemented as 'inline const ...', so no
need to assign them to a constant.
Steven T. Hatton wrote:
> To a large extent, this is a C++ question not specific to Qt. But, given the
> context in which it arose, it seems relevant to Qt. I understand that the
> intent of the examples in _C++ GUI Programming with Qt 4_ are pedagogical and
> therefore should stress clarity over optimal efficiency. Nonetheless, the
> code shown on pg 130 gives me an opportunity to ask a question about coding
> strategy in general.
>
> Page 18 of _C++ Coding Standards_ by Sutter and Alexandrescu tells us "It is
> not premature optimization to reduce spurious temporary copies of objects,
> especially in inner loops, when doing so doesn't impact code complexity." My
> question is whether any clock cycles might be saved by moving some of the
> arithmetic out of the loops? What about calls to functions such as
> settings.spanX()? If these values are unchanged during the loop, can
> anything be gained by assigning them to a constant before entering the loop?
>
> void Plotter::drawGrid(QPainter *painter)
> {
> QRect rect(Margin, Margin,
> width() - 2 * Margin, height() - 2 * Margin);
> if (!rect.isValid())
> return;
>
> PlotSettings settings = zoomStack[curZoom];
> QPen quiteDark = palette().dark().color().light();
> QPen light = palette().light().color();
>
> for (int i = 0; i <= settings.numXTicks; ++i) {
> int x = rect.left() + (i * (rect.width() - 1)
> / settings.numXTicks);
> double label = settings.minX + (i * settings.spanX()
> / settings.numXTicks);
> painter->setPen(quiteDark);
> painter->drawLine(x, rect.top(), x, rect.bottom());
> painter->setPen(light);
> painter->drawLine(x, rect.bottom(), x, rect.bottom() + 5);
> painter->drawText(x - 50, rect.bottom() + 5, 100, 15,
> Qt::AlignHCenter | Qt::AlignTop,
> QString::number(label));
> }
> //...
>
> }
>
--
[ signature omitted ]
Message 3 in thread
Joshua Robinson schrieb:
>
> In many cases those methods implemented as 'inline const ...', so no
> need to assign them to a constant.
On the other hand the following scenario can be a real performace killer
(pseudo-code):
QPainter painter;
foreach (Points p) {
// setting the _same_ colour in the loop eats performance!
painter.setColor (QColor (0, 0, 0));
painter.drawPoint (p, ...);
}
Better:
QPainter painter;
// all points have the same colour, so set it _outside_ of the loop
painter.setColor (QColor (0, 0, 0));
foreach (Points p) {
painter.drawPoint (p, ...);
}
Setting the colour for a QPainter involves a memory allocation
internally (so I've been told during the Qt Developer's Days in Munich
last year) which is costly. So whenever you can use the same colour, set
it once _outside_ the loop! (Off course if each point you want to draw
has a different colour then you have to bite the apple).
In general: take every initialisation out of any loop! I'm also a great
fan of the "Niklaus Wirth paradigm":
1. declaration of variables
2. initialisation of variables
3. use of variables
so I don't like stuff like this anyway:
QString foo;
foo = "42";
while (...) {
// I don't like this - it makes unwanted "shadowing" more
// likely, too
QString bar;
bar = foo;
...
}
While I admit that this kind of technique (declaring variables in the
middle of the code) became fancy with Java (and probably even earlier
with C++, but note that this is not possible in plain C, except at the
beginning of new scopes as in the above example) and I also admit that I
also sometimes use this "lazy" kind of style I still try to avoid it.
Assume that the construction of QString would be costly (realize that
the default constructor is called here): each iteration of the loop this
constructor is called!
In my opinion hence better:
QString foo;
QString bar;
foo = "42";
while (...) {
bar = foo;
...
}
(Now I hear people saying that declaration and initialisation in one
line QString foo ("42"); would be even better, which is actually true -
but in "all-day code" you won't notice the difference ;)
Also be aware of the "Rule of the Great": "Premature optimization is
death for every project" (or so it goes) :)
Cheers, Oliver
--
[ signature omitted ]
Message 4 in thread
On Wednesday 20 December 2006 05:13, Till Oliver Knoll wrote:
> Joshua Robinson schrieb:
> > In many cases those methods implemented as 'inline const ...', so no
> > need to assign them to a constant.
>
> On the other hand the following scenario can be a real performace killer
> (pseudo-code):
>
> QPainter painter;
> foreach (Points p) {
> // setting the _same_ colour in the loop eats performance!
> painter.setColor (QColor (0, 0, 0));
> painter.drawPoint (p, ...);
> }
>
> Better:
>
> QPainter painter;
> // all points have the same colour, so set it _outside_ of the loop
> painter.setColor (QColor (0, 0, 0));
> foreach (Points p) {
> painter.drawPoint (p, ...);
> }
This is the kind of code I am likely to write a lot. Something you learn
pretty quickly with Mathematica is that the way you structure your graphics
code really _does_ make a difference in how long it takes to generate images.
I have less experience with C++ in that area, and the rules of the game are
different.
> Setting the colour for a QPainter involves a memory allocation
> internally (so I've been told during the Qt Developer's Days in Munich
> last year) which is costly. So whenever you can use the same colour, set
> it once _outside_ the loop! (Off course if each point you want to draw
> has a different colour then you have to bite the apple).
That's pretty much how I try to do things unless it gets too hard to follow.
One argument for doing things that way might be that it communicates to the
human reader where in the code invariants are established.
> In general: take every initialisation out of any loop! I'm also a great
> fan of the "Niklaus Wirth paradigm":
>
> 1. declaration of variables
> 2. initialisation of variables
> 3. use of variables
There are arguments both ways. I started out with the Pascal approach, and
now I am firmly rooted in the C++ approach - as local as you can get without
compromising performance and/or clarity. It prevents inadvertent
modification of variables, and helps localize allocation/deallocation with
RAII.
> Assume that the construction of QString would be costly (realize that
> the default constructor is called here): each iteration of the loop this
> constructor is called!
>
> In my opinion hence better:
>
> QString foo;
> QString bar;
>
> foo = "42";
> while (...) {
> bar = foo;
> ...
> }
>
> (Now I hear people saying that declaration and initialisation in one
> line QString foo ("42"); would be even better, which is actually true -
> but in "all-day code" you won't notice the difference ;)
>
>
> Also be aware of the "Rule of the Great": "Premature optimization is
> death for every project" (or so it goes) :)
It makes sense to me to try and understand what your code is doing, and to get
in the habit of writing code that isn't needlessly inefficient. I believe a
lot of C++ coders go too far in trying to do everything with templates
because they can avoid virtual function calls and still have a form of
polymorphism.
--
[ signature omitted ]
Message 5 in thread
On Wed 20-Dec-06 02:37, Steven T. Hatton wrote:
> To a large extent, this is a C++ question not specific to Qt. But, given
> the context in which it arose, it seems relevant to Qt. I understand that
> the intent of the examples in _C++ GUI Programming with Qt 4_ are
> pedagogical and therefore should stress clarity over optimal efficiency.
> Nonetheless, the code shown on pg 130 gives me an opportunity to ask a
> question about coding strategy in general.
>
> Page 18 of _C++ Coding Standards_ by Sutter and Alexandrescu tells us "It
> is not premature optimization to reduce spurious temporary copies of
> objects, especially in inner loops, when doing so doesn't impact code
> complexity." My question is whether any clock cycles might be saved by
> moving some of the arithmetic out of the loops? What about calls to
> functions such as settings.spanX()? If these values are unchanged during
> the loop, can anything be gained by assigning them to a constant before
> entering the loop?
You may save some cycles, but here's my 2c:
In every example in the book we always chose clarity over efficiency.
When writing GUI programs, efficiency is not measured purely in terms of
machine cycles. The time it takes a user to press and release a mouse
button is a very long time from the machine's point of view---plenty of
time in which to do lots of processing, and where the criteria for
"efficiency" that I often use is "fast enough that the user doesn't
notice".
Another issue is programmer time: getting code to run faster often takes
more programmer time, both in the initial optimisation, and in
maintenance. If the optimisation won't even be noticable to users it is
hard to see what you gain. And for optimisations that would make a real
difference, they may be worth making for a program with a large user
base, but maybe not for a program only used by a few people.
Now when it comes to painting, it could be argued that it should always
take place as quickly as possible. But sometimes I think that's a
mistake: If a change happens too fast the user may not realise it has
happened at all (especially if the change is small) and may sit there
waiting for it to happen... So sometimes you want an update to be just
slow enough for the user to notice, but not so slow that they feel
they're being kept waiting.
--
[ signature omitted ]
Message 6 in thread
On Wednesday 20 December 2006 05:03, Mark Summerfield wrote:
> You may save some cycles, but here's my 2c:
>
> In every example in the book we always chose clarity over efficiency.
>
> When writing GUI programs, efficiency is not measured purely in terms of
> machine cycles. The time it takes a user to press and release a mouse
> button is a very long time from the machine's point of view---plenty of
> time in which to do lots of processing, and where the criteria for
> "efficiency" that I often use is "fast enough that the user doesn't
> notice".
If only I could get the spam filter to understand that. It's hopeless!
> Another issue is programmer time: getting code to run faster often takes
> more programmer time, both in the initial optimisation, and in
> maintenance. If the optimisation won't even be noticable to users it is
> hard to see what you gain. And for optimisations that would make a real
> difference, they may be worth making for a program with a large user
> base, but maybe not for a program only used by a few people.
My thought is that it makes sense to understand the relative performance
tradeoffs in common situations, and to favor the better performing code when
all other factors are equal. If I learn to write efficient code as part of
my coding style, then, once that initial investment has been made, writing
efficient code should cost nothing additional in comparison to the less
efficient alternatives. It may, in many cases, improve clarity.
> Now when it comes to painting, it could be argued that it should always
> take place as quickly as possible. But sometimes I think that's a
> mistake: If a change happens too fast the user may not realise it has
> happened at all (especially if the change is small) and may sit there
> waiting for it to happen... So sometimes you want an update to be just
> slow enough for the user to notice, but not so slow that they feel
> they're being kept waiting.
Lets take the topic of the section of the book under discussion: Double
Buffering. I'm really not sure what's happening in terms of memory
allocation. It seems that every resize event requires a new allocation of a
QPixmap which we draw on, and then use to replace the previous QPixmap which
gets handed back to the resource gods, or something like that. I assume a
deallocation takes place as part of the QStylePainter::drawPixmap(0, 0,
pixmap);
I guess I could chalk it up to "magic happens" until I have a problem.
Nonetheless, I would like to understand what is likely to be taking place.
It seems unlikely that my program would continue to grab new chunks of memory
without reusing some of what is freed. OTOH, there's no GC going on, AFAIK.
Do you happen to have any insight into this?
--
[ signature omitted ]
Message 7 in thread
On Wed 20-Dec-06 18:54, Steven T. Hatton wrote:
> On Wednesday 20 December 2006 05:03, Mark Summerfield wrote:
[snip]
> > Another issue is programmer time: getting code to run faster often takes
> > more programmer time, both in the initial optimisation, and in
> > maintenance. If the optimisation won't even be noticable to users it is
> > hard to see what you gain. And for optimisations that would make a real
> > difference, they may be worth making for a program with a large user
> > base, but maybe not for a program only used by a few people.
>
> My thought is that it makes sense to understand the relative performance
> tradeoffs in common situations, and to favor the better performing code
> when all other factors are equal. If I learn to write efficient code as
> part of my coding style, then, once that initial investment has been made,
> writing efficient code should cost nothing additional in comparison to the
> less efficient alternatives. It may, in many cases, improve clarity.
I agree.
> > Now when it comes to painting, it could be argued that it should always
> > take place as quickly as possible. But sometimes I think that's a
> > mistake: If a change happens too fast the user may not realise it has
> > happened at all (especially if the change is small) and may sit there
> > waiting for it to happen... So sometimes you want an update to be just
> > slow enough for the user to notice, but not so slow that they feel
> > they're being kept waiting.
>
> Lets take the topic of the section of the book under discussion: Double
> Buffering. I'm really not sure what's happening in terms of memory
> allocation. It seems that every resize event requires a new allocation of
> a QPixmap which we draw on, and then use to replace the previous QPixmap
> which gets handed back to the resource gods, or something like that. I
> assume a deallocation takes place as part of the
> QStylePainter::drawPixmap(0, 0, pixmap);
>
> I guess I could chalk it up to "magic happens" until I have a problem.
> Nonetheless, I would like to understand what is likely to be taking place.
> It seems unlikely that my program would continue to grab new chunks of
> memory without reusing some of what is freed. OTOH, there's no GC going
> on, AFAIK. Do you happen to have any insight into this?
I don't happen to know how this works behind the scenes. However, I
don't consider anything in Qt to be "magic", because nothing is
hidden---if you want to know, you just have to read the source.
--
[ signature omitted ]
Message 8 in thread
On Thursday 21 December 2006 02:20, Mark Summerfield wrote:
> On Wed 20-Dec-06 18:54, Steven T. Hatton wrote:
> > On Wednesday 20 December 2006 05:03, Mark Summerfield wrote:
> > Lets take the topic of the section of the book under discussion: Double
> > Buffering. I'm really not sure what's happening in terms of memory
> > allocation. It seems that every resize event requires a new allocation
> > of a QPixmap which we draw on, and then use to replace the previous
> > QPixmap which gets handed back to the resource gods, or something like
> > that. I assume a deallocation takes place as part of the
> > QStylePainter::drawPixmap(0, 0, pixmap);
> >
> > I guess I could chalk it up to "magic happens" until I have a problem.
> > Nonetheless, I would like to understand what is likely to be taking
> > place. It seems unlikely that my program would continue to grab new
> > chunks of memory without reusing some of what is freed. OTOH, there's no
> > GC going on, AFAIK. Do you happen to have any insight into this?
>
> I don't happen to know how this works behind the scenes. However, I
> don't consider anything in Qt to be "magic", because nothing is
> hidden---if you want to know, you just have to read the source.
Well, yes, but I'm not sure that would even answer all of this. Since I use
Linux I could also look at the OS source, and I guess the GCC source may also
have some bearing on this. Qt /may/ be handling this, but I doubt it. I
will take a look when I find time. What I'm really wondering about is what
happens in general when I grab a chunk of memory then grab another chunk of a
different size and release the first one repeatedly in rapid succession.
I don't even know if that is determined by the allocator provided by the C++
implementation, or by the OS.
--
[ signature omitted ]
Message 9 in thread
On Fri 22-Dec-06 02:40, Steven T. Hatton wrote:
[snip]
> Well, yes, but I'm not sure that would even answer all of this. Since I
> use Linux I could also look at the OS source, and I guess the GCC source
> may also have some bearing on this. Qt /may/ be handling this, but I doubt
> it. I will take a look when I find time. What I'm really wondering about
> is what happens in general when I grab a chunk of memory then grab another
> chunk of a different size and release the first one repeatedly in rapid
> succession.
>
> I don't even know if that is determined by the allocator provided by the
> C++ implementation, or by the OS.
It will depend on the compiler. Some (all?) have sub-allocators.
But I think this is a blind alley: the next version of your OS or
compiler may change everything in this regard. I would program to the
high-level API and not worry at all about performance. If it turns out
that you have performance problems, then use a profiler. Trying to write
"generally optimized code" will take much more time than the payback in
performance (if there is any improvement at all); much better to deal
with specific bottlenecks if they occur. IMO the biggest performance
issue is not "have I coded this loop tightly", but "have I used the
right data structure". If you're often sorting data or doing linear
searches for example...
--
[ signature omitted ]
Message 10 in thread
> -----Original Message-----
> From: Mark Summerfield [mailto:m.n.summerfield@xxxxxxxxxxxxxx] On
Behalf
> Of Mark Summerfield
> Sent: Friday, December 22, 2006 12:14 AM
> To: qt-interest@xxxxxxxxxxxxx
> Cc: Steven T. Hatton
> Subject: Re: C++ GUI Programming with Qt 4: pg 130
>
> On Fri 22-Dec-06 02:40, Steven T. Hatton wrote:
> [snip]
> > Well, yes, but I'm not sure that would even answer all of this.
Since I
> > use Linux I could also look at the OS source, and I guess the GCC
source
> > may also have some bearing on this. Qt /may/ be handling this, but
I
> doubt
> > it. I will take a look when I find time. What I'm really wondering
> about
> > is what happens in general when I grab a chunk of memory then grab
> another
> > chunk of a different size and release the first one repeatedly in
rapid
> > succession.
> >
> > I don't even know if that is determined by the allocator provided by
the
> > C++ implementation, or by the OS.
>
> It will depend on the compiler. Some (all?) have sub-allocators.
> But I think this is a blind alley: the next version of your OS or
> compiler may change everything in this regard. I would program to the
> high-level API and not worry at all about performance. If it turns out
> that you have performance problems, then use a profiler. Trying to
write
> "generally optimized code" will take much more time than the payback
in
> performance (if there is any improvement at all); much better to deal
> with specific bottlenecks if they occur. IMO the biggest performance
> issue is not "have I coded this loop tightly", but "have I used the
> right data structure". If you're often sorting data or doing linear
> searches for example...
>
> --
While I tend to agree with Mark here. The higher level of abstraction
from the object code, the better.. :)
However, there are some, simple consistent coding styles that will
perform better.
Now, I know QT has made some of these coding styles obsolete :) but
IMHO, they should still be used.
For example, I don't pass containers as return values, and I don't pass
them as constants via copy as opposed to constant references.
I know QT has light copy and shared internals, but relying on that I
think is asking for disaster... We cant always code in Qt :(
Scott
--
[ signature omitted ]
Message 11 in thread
On Friday 22 December 2006 04:10, Scott Aron Bloom wrote:
> While I tend to agree with Mark here. The higher level of abstraction
> from the object code, the better.. :)
That's what the Qt crowd tells me until I want some gratuitous luxury such as
QContainer::at() that throws an exception. Then I'm told I want the Sun, the
Moon and all the stars. ;)
> However, there are some, simple consistent coding styles that will
> perform better.
>
> Now, I know QT has made some of these coding styles obsolete :) but
> IMHO, they should still be used.
>
> For example, I don't pass containers as return values, and I don't pass
> them as constants via copy as opposed to constant references.
>
> I know QT has light copy and shared internals, but relying on that I
> think is asking for disaster... We cant always code in Qt :(
I like the expressiveness of using constant references over light copy. It
tells the human reader what the intent is. I've gotten myself wrapped around
the axel more than once with QtXml doing that. I think, in principle, I
could make it work, but I've found that I often end up with something that
breaks five calls away, and end up removing all the '&', etc.
--
[ signature omitted ]
Message 12 in thread
On Friday 22 December 2006 03:14, Mark Summerfield wrote:
> On Fri 22-Dec-06 02:40, Steven T. Hatton wrote:
> [snip]
>
> > Well, yes, but I'm not sure that would even answer all of this. Since I
> > use Linux I could also look at the OS source, and I guess the GCC source
> > may also have some bearing on this. Qt /may/ be handling this, but I
> > doubt it. I will take a look when I find time. What I'm really
> > wondering about is what happens in general when I grab a chunk of memory
> > then grab another chunk of a different size and release the first one
> > repeatedly in rapid succession.
> >
> > I don't even know if that is determined by the allocator provided by the
> > C++ implementation, or by the OS.
>
> It will depend on the compiler. Some (all?) have sub-allocators.
> But I think this is a blind alley: the next version of your OS or
> compiler may change everything in this regard. I would program to the
> high-level API and not worry at all about performance.
Regarding the specific question about double buffering, it was 95% idle
curiosity. I guess if I were writing cross-platform production code OS
dependency could become an issue.
> If it turns out
> that you have performance problems, then use a profiler. Trying to write
> "generally optimized code" will take much more time than the payback in
> performance (if there is any improvement at all); much better to deal
> with specific bottlenecks if they occur. IMO the biggest performance
> issue is not "have I coded this loop tightly", but "have I used the
> right data structure". If you're often sorting data or doing linear
> searches for example...
The one area where I have found that choice of code structure makes a
noticeable difference is in graphics. Particularly 3D graphics. I will
observe that you and Jasmin used a static_cast<> in the spreadsheet code on
pg. 98 where a dynamic_cast<> might have been marginally safer. I assume
that was for performance reasons. That probably made sense when the code was
written, but my understanding is that dynamic_cast is a good candidate for
performance enhancement (and in GCC may already have been vastly improved).
I guess the moral of the story is that there is no easy answer.
--
[ signature omitted ]
Message 13 in thread
"Steven T. Hatton" <hattons@xxxxxxxxxxxxxxxxxx> wrote in message
news:200612221336.22391.hattons@xxxxxxxxxxxxxxxxxxxxx
> The one area where I have found that choice of code structure makes a
> noticeable difference is in graphics. Particularly 3D graphics. I will
> observe that you and Jasmin used a static_cast<> in the spreadsheet code
> on
> pg. 98 where a dynamic_cast<> might have been marginally safer. I assume
> that was for performance reasons. That probably made sense when the code
> was
> written, but my understanding is that dynamic_cast is a good candidate for
> performance enhancement (and in GCC may already have been vastly
> improved).
>
> I guess the moral of the story is that there is no easy answer.
The problem with optimizing graphics is that is likely going to be platform
dependant AND compiler dependant. As for the dynamic cast vs. static cast,
I think that in every situation a static cast would be optimal if you know
that
it will succeed. Dynamic cast is only useful if you want to check that it
succeeds
It includes some overhead to achieve this. As for being safer, if the
static cast
compiles, then it should work, no? I'm not sure what you mean by dynamic
cast
being safer.
Actually, with Qt, if I have to cast and I can't use a static cast, a
qobject cast usually works.
I don't usually even enable RTTI in my projects. Most of my projects are
MSVC these days
though so YMMV.
--
[ signature omitted ]
Message 14 in thread
On Friday 22 December 2006 19:10, Duane Hebert wrote:
> "Steven T. Hatton" <hattons@xxxxxxxxxxxxxxxxxx> wrote in message
> news:200612221336.22391.hattons@xxxxxxxxxxxxxxxxxxxxx
>
> > The one area where I have found that choice of code structure makes a
> > noticeable difference is in graphics. Particularly 3D graphics. I will
> > observe that you and Jasmin used a static_cast<> in the spreadsheet code
> > on
> > pg. 98 where a dynamic_cast<> might have been marginally safer. I assume
> > that was for performance reasons. That probably made sense when the code
> > was
> > written, but my understanding is that dynamic_cast is a good candidate
> > for performance enhancement (and in GCC may already have been vastly
> > improved).
> >
> > I guess the moral of the story is that there is no easy answer.
>
> The problem with optimizing graphics is that is likely going to be platform
> dependant AND compiler dependant. As for the dynamic cast vs. static cast,
> I think that in every situation a static cast would be optimal if you know
> that
> it will succeed. Dynamic cast is only useful if you want to check that it
> succeeds
> It includes some overhead to achieve this. As for being safer, if the
> static cast
> compiles, then it should work, no? I'm not sure what you mean by dynamic
> cast
> being safer.
You /can/ static cast to an incorrect derived type.
Â5.2.9/5 "An lvalue of type âcv1 Bâ, where B is a class type, can be cast to
type âreference to cv2 Dâ, where D is a class derived (clause 10) from B, if
a valid standard conversion from â _pointer_ _to_ _D_ â _to_ â _pointer_ _to_
_B_ â exists (4.10), cv2 is the same cv-qualification as, or greater
cv-qualification than, cv1, and B is not a virtual base class of D. The
result is an lvalue of type âcv2 D.â If the lvalue of type âcv1 Bâ is
actually a sub-object of an object of type D, the lvalue refers to the
enclosing object of type D. Otherwise, the result of the cast is undefined."
> Actually, with Qt, if I have to cast and I can't use a static cast, a
> qobject cast usually works.
> I don't usually even enable RTTI in my projects. Most of my projects are
> MSVC these days
> though so YMMV.
Disabling RTTI is not an option with OSG. I need to do (or find) some
benchmarking on GCC and dynamic_casts. I've been told they improved it
considerably in the past year or so. The same source claimed that MSVC's
dynamic_cast has pretty bad performance.
--
[ signature omitted ]
Message 15 in thread
"Steven T. Hatton" <hattons@xxxxxxxxxxxxxxxxxx> wrote in message
news:200612222216.04306.hattons@xxxxxxxxxxxxxxxxxxxxx
>You /can/ static cast to an incorrect derived type.
>§5.2.9/5 "An lvalue of type "cv1 B", where B is a class type, can be cast
>to
>type "reference to cv2 D", where D is a class derived (clause 10) from B,
>if
>a valid standard conversion from " _pointer_ _to_ _D_ " _to_ " _pointer_
>_to_
>_B_ " exists (4.10), cv2 is the same cv-qualification as, or greater
>cv-qualification than, cv1, and B is not a virtual base class of D. The
>result is an lvalue of type "cv2 D." If the lvalue of type "cv1 B" is
|>actually a sub-object of an object of type D, the lvalue refers to the
>enclosing object of type D. Otherwise, the result of the cast is
>undefined."
So this is basically saying that a cast from a const base to a const &
of a derived class is defined but not from derived to base. And that
the derived to base cast will have undefined behavior. I love UDB
almost as much as I love reading standardese <g>.
So if you have a situation where you don't know that you're slicing
you need a dynamic cast. OK.
>Disabling RTTI is not an option with OSG. I need to do (or find) some
>benchmarking on GCC and dynamic_casts. I've been told they improved it
>considerably in the past year or so. The same source claimed that MSVC's
>dynamic_cast has pretty bad performance.
I've heard the same thing. I haven't benchmarked it on either compiler.
We did notice pretty poor performance with Borland compilers
though (BCB5). That's why we don't tend to use RTTI.
I don't use OpenGL. I didn't realize that it depended on
RTTI. As I say, in most (actually every) case where we
can't use a static cast, we use a qobject cast.
If you can benchmark this, posting the results would be
useful.
--
[ signature omitted ]
Pages: Prev | 1 | 2 | Next