Et unum hominem, et plures in infinitum, quod quis velit, heredes facere licet - wolno uczynić spadkobiercą i jednego człowieka, i wielu, bez ograniczeń, ilu kto chce.

[ Pobierz całość w formacie PDF ]

doesn't necessarily impose additional runtime penalties. If the compiler can resolve the
call statically, no extra overhead is incurred. Furthermore, a very short virtual function
can be inlined in this case. In the following example, a clever compiler can resolve the
calls of the virtual member functions statically:
#include
using namespace std;
class V
{
public:
virtual void show() const { cout
};
class W : public V
{
public:
void show() const { cout
};
void f(V & v, V *pV)
{
v.show();
pV->show();
}
void g()
{
V v;
f(v, &v);
}
int main()
{
g();
return 0;
}
If the entire program appears in a single translation unit, the compiler can perform an
inline substitution of the call of the function g() in main(). The invocation of f() within
g() can also be inlined, and because the dynamic type of the arguments that are passed to
f() is known at compile time, the compiler can resolve the virtual function calls inside
f() statically. There is no guarantee that every compiler actually inlines all the function
calls; however, some compilers certainly take advantage of the fact that the dynamic type
of the arguments of f() can be determined at compile time, and avoid the overhead of
dynamic binding in this case.
Function Objects Versus Function Pointers
The benefits of using function objects instead of function pointers (function objects are
discussed in Chapter 10 and in Chapter 3, "Operator Overloading") are not limited to
genericity and easier maintenance. Furthermore, compilers can inline the call of a
function object, thereby enhancing performance even further (inlining a function pointer
call is rarely possible).
A Last Resort
The optimization techniques that have been presented thus far do not dictate design
compromises or less readable code. In fact, some of them improve the software's
robustness and the ease of maintenance. Packing a long argument list within a class
object, const declarations, and using function objects rather than function pointers
provide additional benefits on top of the performance boost. Under strict time and
memory constraints, however, these techniques might not suffice; additional tweaks are
sometimes required, which affect the portability and extensibility of the software. The
techniques that are presented in this section are to be used only as a last resort, and only
after all the other optimizations have been applied.
Disabling RTTI and Exception Handling Support
When you port pure C code to a C++ compiler, you might discover a slight performance
degradation. This is not a fault in the programming language or the compiler, but a matter
of compiler tuning. All you have to do to gain the same (or better) performance that you
might get from a C compiler is switch off the compiler's RTTI and exception handling
support. Why is this? In order to support RTTI or exception handling, a C++ compiler
inserts additional "scaffolding" code to the original source file. This increases the
executable size a little, and imposes slight runtime overhead (the overhead of exception
handling and RTTI are discussed in Chapter 6, "Exception Handling," and Chapter 7,
"Runtime Type Identification", respectively). When pure C is used, this additional code is
unnecessary. Please note, however, that you should not attempt to apply this tweak with
C++ code or C code that uses any C++ constructs such as operator new and virtual
functions.
Inline Assembly
Time-critical sections of C++ code can be rewritten in native assembly code. The result
can be a significant increase in speed. Note, however, that this measure is not to be taken
lightly because it makes future modifications much more difficult. Programmers who
maintain the code might not be familiar with the particular assembly language that is
used, or they might have no prior experience in assembly language at all. Furthermore,
porting the software to other platforms requires rewriting of the assembly code parts (in
some instances, upgrading the processor can also necessitate rewriting). In addition,
developing and testing assembly code is an arduous task that can take much more time
than developing and testing code that is written in a high-level language.
Generally, operations that are coded in assembly are low-level library functions. On most
implementations, for example, the standard library functions memset() and strcpy() are
written in native assembly code. C and C++ enable the programmer to embed inline
assembly code within an asm block. For example
asm
{
mov a, ecx
//...
}
Interacting with the Operating System Directly
API functions and classes enable you to interact with the operating system. Sometimes,
however, executing a system command directly can be much faster. For this purpose, you
can use the standard function system() that takes a shell command as a const char *.
For example, on a DOS/Windows system, you can display the files in the current
directory as follows:
#include
using namespace std;
int main()
{
system("dir"); //execute the "dir" command
}
Here again, the tradeoff is between speed on the one hand and portability and future
extensibility on the other hand.
Conclusions
In an ideal world, software designers and developers might focus their efforts on robust, [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • jutuu.keep.pl
  • Menu

    Cytat


    Fallite fallentes - okłamujcie kłamiących. Owidiusz
    Diligentia comparat divitias - pilność zestawia bogactwa. Cyceron
    Daj mi właściwe słowo i odpowiedni akcent, a poruszę świat. Joseph Conrad
    I brak precedensu jest precedensem. Stanisław Jerzy Lec (pierw. de Tusch - Letz, 1909-1966)
    Ex ante - z przed; zanim; oparte na wcześniejszych założeniach.