I l@ve RuBoard Previous Section Next Section

2.5 Declaring a Function Inline

Recall that fibon_elem() returns the Fibonacci element at a user-specified position within the sequence. In our original implementation, it calculates the sequence up to the requested position with each invocation. It also tests whether the requested position is reasonable. We can simplify its implementation by factoring subtasks into separate functions:



bool is_size_ok( int size ) 


{ 


     const int max_size = 1024; 


     if ( size <= 0 || size > max_size ) 


     { 


          cerr << "Oops: requested size is not supported : " 


               << size << " -- can't fulfill request.\n"; 


          return false; 


     } 


     return true; 


} 





// calculate up to size elements of Fibonacci sequence 


// return address of static container holding elements 


const vector<int> *fibon_seq( int size ) 


{ 


   static vector< int > elems; 


   if ( ! is_size_ok( size )) 


        return 0; 





   for ( int ix = elems.size(); ix < size; ++ix ) 


        if ( ix == 0 || ix == 1 ) 


             elems.push_back( 1 ); 


        else elems.push_back( elems[ix-1]+elems[ix-2] ); 


   return &elems; 


} 





// returns the Fibonacci element at position pos 


// (we must adjust by 1 because first element is stored at 0) 


// returns false if position is unsupported 


bool fibon_elem( int pos, int &elem ) 


{ 


    const vector<int> *pseq = fibon_seq( pos ); 





    if ( ! pseq ) 


       {  elem = 0; return false; } 





    elem = (*pseq)[ pos-1 ]; 


    return true; 


} 

By factoring size checking into is_size_ok() and the calculation of the Fibonacci elements into fibon_seq(), we make fibon_elem() simpler to implement and understand. In addition, these two functions are now available to other applications.

The drawback is that fibon_elem() now requires three function calls to complete its operation, whereas previously it required only one. Is this additional overhead critical? That depends on the context of its use. If its performance should prove unacceptable, one solution is to fold the three functions back into one. In C++, an alternative solution is to declare the functions as inline.

An inline function represents a request to the compiler to expand the function at each call point. With an inline function, the compiler replaces the function call with a copy of the code to be executed. In effect, this allows us to benefit from the performance improvement of folding the functions back into fibon_elem() while still maintaining the three functions as independent operations.

We declare a function inline by prefixing its definition with the inline keyword:



// ok: now fibon_elem() is an inline function 


inline bool fibon_elem( int pos, int &elem ) 


       {  /* definition same as above */ } 

The inline specification is only a request to the compiler. Whether the compiler actually honors the request is implementation-dependent. (For a discussion of why the inline specification is only a request, see Section 7.1.1 of [STROUSTRUP97].)

In general, the best candidate functions for inlining, such as fibon_elem() and is_size_ok(), are small, frequently invoked, and not computationally complex.

The definition of an inline function is usually placed within a header file. For it to be expanded, its definition must be available before its call. (This is discussed further in Section 2.9. )

    I l@ve RuBoard Previous Section Next Section