(9 ratings)   
By: www.glenmccl.com
Such a function is written just like a regular C or C++ function. But it IS a function and not simply a macro; macros don't really obey the rules of C++ and therefore can introduce problems. Note also that one could use C++ templates to write this...
Added: 13 June 2008    Views: 343  
PathComputers    Programming    C++
Keywords: computers   programming   c   language   object   pointer   coder   code   buyer  
Do you like this tutorial? Now you can support our team to add more :     
 
 
 

Suppose that you wish to write a function in C to compute the maximum of two numbers. One way would be to say:

        int max(int a, int b)
{
return (a > b ? a : b);
}

But calling a frequently-used function can be a bit slow, and so you instead use a macro:

        #define max(a, b) ((a) > (b) ? (a) : (b))

The extra parentheses are required to handle cases like:

        max(a = b, c = d)

This approach can work pretty well. But it is error-prone due to the extra parentheses and also because of side effects like:

        max(a++, b++)

An alternative in C++ is to use inline functions:

        inline int max(int a, int b)
{
return (a > b ? a : b);
}

Such a function is written just like a regular C or C++ function. But it IS a function and not simply a macro; macros don't really obey the rules of C++ and therefore can introduce problems. Note also that one could use C++ templates to write this function, with the argument types generalized to any numerical type.

If an inline function is a member function of a C++ class, there are a couple of ways to write it:

        class A {
public:
void f() { /* stuff */ } // "inline" not needed
};

or:

        class A {
public:
inline void f();
};

inline void A::f()
{
/* stuff */
}

The second style is often a bit clearer.

The "inline" keyword is merely a hint to the compiler or development environment. Not every function can be inlined. Some typical reasons why inlining is sometimes not done include:

        - the function calls itself, that is, is recursive

- the function contains loops such as for(;;) or while()

- the function size is too large

Most of the advantage of inline functions comes from avoiding the overhead of calling an actual function. Such overhead includes saving registers, setting up stack frames, and so on. But with large functions the overhead becomes less important.

Inline functions present a problem for debuggers and profilers, because the function is expanded at the point of call and loses its identity. A compiler will typically have some option available to disable inlining.

Inlining tends to blow up the size of code, because the function is expanded at each point of call. The one exception to this rule would be a very small inline function, such as one used to access a private data member:

        class A {
int x;
public:
int getx() {return x;}
};

which is likely to be both faster and smaller than its non-inline counterpart.

A simple rule of thumb when doing development is not to use inline functions initially. After development is mostly complete, you can profile the program to see where the bottlenecks are and then change functions to inlines as appropriate.

Here's a complete program that uses inline functions as part of an implementation of bit maps. Bit maps are useful in storing true/false values efficiently. Note that in a couple of places we could use the new bool fundamental type in place of ints. Also note that this implementation assumes that chars are 8 bits in width; there's no fundamental reason they have to be (in Java(tm) the Unicode character set is used and chars are 16 bits).

This example runs about 50% faster with inlines enabled.

        #include <assert.h>
#include <stdlib.h>
#include <string.h>

//#define inline

class Bitmap {
typedef unsigned long UL; // type of specified bit num
UL len; // number of bits
unsigned char* p; // pointer to the bits
UL size(); // figure out bitmap size
public:
Bitmap(UL); // constructor
~Bitmap(); // destructor
void set(UL); // set a bit
void clear(UL); // clear a bit
int test(UL); // test a bit
void clearall(); // clear all bits
};

// figure out bitmap size
inline Bitmap::UL Bitmap::size()
{
return (len - 1) / 8 + 1;
}

// constructor
inline Bitmap::Bitmap(UL n)
{
assert(n > 0);
len = n;
p = new unsigned char[size()];
assert(p);
clearall();
}

// destructor
inline Bitmap::~Bitmap()
{
delete [] p;
}

// set a bit
inline void Bitmap::set(UL bn)
{
assert(bn < len);
p[bn / 8] |= (1 << (bn % 8));
}

// clear a bit
inline void Bitmap::clear(UL bn)
{
assert(bn < len);
p[bn / 8] &= ~(1 << (bn % 8));
}

// test a bit, return non-zero if set
inline int Bitmap::test(UL bn)
{
assert(bn < len);
return p[bn / 8] & (1 << (bn % 8));
}

// clear all bits
inline void Bitmap::clearall()
{
memset(p, 0, size());
}

#ifdef DRIVER
main()
{
const unsigned long N = 123456L;
int i;
long j;
int k;
int r;

for (i = 1; i <= 10; i++) {
Bitmap bm(N);

// set all bits then test

for (j = 0; j < N; j++)
bm.set(j);
for (j = 0; j < N; j++)
assert(bm.test(j));

// clear all bits then test

for (j = 0; j < N; j++)
bm.clear(j);
for (j = 0; j < N; j++)
assert(!bm.test(j));

// run clearall() then test

bm.clearall();
for (j = 0; j < N; j++)
assert(!bm.test(j));

// set and clear random bits

k = 1000;
while (k-- > 0) {
r = rand() & 0xffff;
bm.set(r);
assert(bm.test(r));
bm.clear(r);
assert(!bm.test(r));
}
}

return 0;
}
#endif


About the Author :
Inline Functions
Articles and Tutorials Directory by www.learnfobia.com
 Rate this tutorial : Rate 1Rate 2Rate 3Rate 4Rate 5
  |    Add to Favorites
  |    Send to Friend
  |    Print
Comments