Declaring References to Functions You can declare a reference to a function, just like you can declare a pointer to a function. For example: Code: void f(int n) { ++n; } int main() { void (&rf) (int) = f; //bind rf as a reference to f() rf(5); //call f() through its reference } The major difference between a pointer and a reference to a function is that the latter must always be bound to an existing function (i.e., it may not be null or dangling), and you cannot re-bind another function to it once you have initialized it.
Hide Function Pointer Declarations With a typedef Can you tell what the following declaration means? Code: void (*p[10]) (void (*)() ); Only few programmers can tell that p is an "array of 10 pointers to a function returning void and taking a pointer to another function that returns void and takes no arguments." The cumbersome syntax is nearly indecipherable. However, you can simplify it considerably by using typedef declarations. First, declare a typedef for "pointer to a function returning void and taking no arguments" as follows: Code: typedef void (*pfv)(); Next, declare another typedef for "pointer to a function returning void and taking a pfv" based on the typedef we previously declared: Code: typedef void (*pf_taking_pfv) (pfv); Now that we have created the pf_taking_pfv typedef as a synonym for the unwieldy "pointer to a function returning void and taking a pfv", declaring an array of 10 such pointers is a breeze: Code: pf_taking_pfv p[10];
No Pointer Arithmetics Outside Array Bounds! Sometimes it is tempting to let a pointer point to a location that is slightly beyond an array's index range. For example, consider the following self-defined array class, which allows you to define arrays whose index ranges do not necessarily start at zero: Code: template class MyArray { T* ptr; int f, l; public: MyArray (int first, int last) : f(first), l(last) { ptr = new T [last-first+1]; // Why +1? ptr -= first; } T& operator[] (int index) { return ptr[index]; } // Further methods }; The trick is simple and elegant and might result in very efficient code: Since the address stored in ptr differs from the address of the real array by the value of first, first need not be subtracted from index in operator[]. A neat trick, right? Unfortunately, the C++ standard draft says that a call to operator[] would result in undefined behavior. Even if it runs fine on your system, there are definitely systems on which this is not the case. An expression with pointer arithmetics is well defined only if all involved pointers and all results of partial expressions point to elements of one--and only one--array.
Pointers to Members of a Template Class You can define a pointer to a class template member. For example, you can use the specialization vector<int>: Code: typedef void (vector< int >::*v_vi_szt) (size_t); // v_vi_szt is used to hide the unwieldy syntax v_vi_szt reserve_ptr = &vector< int >::reserve; The only difference from ordinary pointers to class members is that you are required to use a template specialization, since a template name per se is not a type. In other words, you have to define a separate pointer to member for every specialization used. In the following example, vector <string> specialization is used (no typedef applied in this case): Code: void (vector< string >::*v_vs_szt) (size_t) = &vector< string >::reserve; // string specialization
Uses of the ptrdiff_t Data Type C and C++ define a special type for pointer arithmetic, namely ptrdiff_t, which is a typedef of a platform-specific signed integral type. You can use a variable of type ptrdiff_t to store the result of subtracting and adding pointers. For example: Code: #include <stdlib.h> int main() { int buff[4]; ptrdiff_t diff = (&buff[3]) - buff; // diff = 3 diff = buff -(&buff[3]); // -3 } What are the advantages of using ptrdiff_t? First, the name ptrdiff_t is self-documenting and helps the reader understand that the variable is used in pointer arithmetic exclusively. Secondly, ptrdiff_t is portable: its underlying type may vary across platforms, but you don't need to make changes in the code when porting it.
Prefer References Over Pointers Even experienced C++ programmers who have prior experience with C tend to use pointers excessively whereas references may be a better choice. Pointers may result in bugs like the following: Code: bool isValid( const Date *pDate); void f() { Date *p = new Date(); //default: current date //...many lines of code delete p; //p is now a “dangling pointer” bool valid = isValid(p); //oops! undefined behavior p = NULL; valid = isValid(p) //ops! null pointer dereferencing; //most likely will lead to a crash } The use of references eliminates the notorious bugs related to pointers: null pointer assignment and dangling pointer dereferencing, since a reference is always bound to a valid object: Code: bool isValid( const Date& date); //reference version void f() { Date date; //default: current date //...many lines of code bool valid = isValid(date); //always safe date += 100; //add 100 days valid = isValid(date) //always safe }
Beware of Aliasing Whenever your class contains pointers, references, or handles, you need to define a copy constructor and assignment operator. Otherwise, the compiler-generated copy constructor and assignment operator will result in aliasing, that is to say, the same resource will be used simultaneously by more than one object and will also be released more than once - with disastrous results: Code: class Document { private: FILE *pdb; public: Document(FILE *f =NULL) : pdb(f){} //no user-defined copy constructor or operator= ~Document() {fclose(pdb);} //... }; void assign(Documnet d&) { Document temp("letter.doc"); d = temp; //Aliasing; both d and temp now point to the same file }//temp's destructor is now automatically called and closes file letter.doc while d is still using it void main() { Document doc; assign(doc); //OOPS! doc now uses a file which has just been closed }//OOPS! doc's destructor is now invoked and closes 'letter.doc' once again
auto_ptr<>: your safe guard against memory leaks The Standard Library supplies the class template auto_ptr<> which automatically deallocates heap memory. Likewise, local objects are reclaimed in case of exiting their scope or during "stack unwinding" caused by an exception. This technique can avoid memory leakage in the case of uncaught exception or even simplify programming by sparing the hassle of explicitly deleting every object allocated using operator new. The auto_ptr<> class template is declared in the standard <memory> header. Code: #include <memory> //auto_ptr<> declaration #include <iostream> using namespace std; class Date{ /*...*/}; void DisplayDate() { //now create a local object of type auto_ptr<Date> auto_ptr<Date> pd (new Date); //now pd is owned by the template object cout<<pd->DateString(); //note: pd is automatically deleted by the destructor of auto_ptr; it shouldn't be deleted by programmer } In other words, the auto_ptr<> instance, pd, can be used like an ordinary pointer to Date but it behaves like a local object in respect to its automatic destruction.
Why you shouldn't store auto_ptr objects in STL containers Most C++ users already know that they shouldn't use auto_ptr objects as elements of STL containers. However, fewer users know exactly why this is so. The C++ Standard says that an STL element must be "copy-constructible" and "assignable." These fancy words simply mean you can safely assign or copy one object to another and get two independent and logically identical copies. In particular, the state of the original object shouldn't change when it is copied to the target object. This is not the case with auto_ptr, though: copying or assigning one auto_ptr to another makes changes to the original, in addition to the obvious changes to the copy. To be more specific, the original object transfers ownership of the pointer to the target, and the pointer in the original object becomes null. Imagine what would happen if you did something like this: Code: class Foo{}; vector < auto_ptr <Foo> > vf; //a vector of auto_ptr's //..fill vf int g() { auto_ptr <Foo> temp = vf[0]; // vf[0] becomes null } When temp is initialized, the member vf[0] is changed: its pointer becomes null. Any attempt to use that element will cause a runtime crash. This situation is likely to occur whenever you copy an element from the container. Remember that even if your code does not perform any explicit copy or assignment operations, many algorithms (swap(), random_shuffle(), sort(), and many others) create a temporary copy of one or more container elements. Furthermore, certain member functions of the container may create a temporary copy of one or more elements, thereby nullifying them. Any subsequent attempt to the container elements is therefore undefined. Several Visual C++ users report that they have never encountered any problems with using auto_ptr in STL containers. This is because the auto_ptr implementation of Visual C++ (all versions thereof) is outdated and relies on an obsolete specification. When Microsoft decides to catch up with the current ANSI/ISO C++ Standard and change their Standard Library accordingly, code that uses auto_ptr in STL containers will manifest serious malfunctions. To conclude, you shouldn't use auto_ptr in STL containers. Either use bare pointers or use other smart pointer classes instead of auto_ptr
Iterators Aren't Pointers Suppose you define a the following list object and you need the address of one of its elements: Code: std::list <int> li; std::list <int>::iterator iter = li.begin(); In many contexts, iter functions like a pointer. However, when you need a real pointer to a container's element, you can't use an iterator: Code: int func(int * p); int main() { func(iter); // error, iter is not a pointer to int } The problem is that in general, iterators aren't pointers. Rather, they are usually implemented as objects. To get a pointer to the element an iterator refers to, you need to "dereference" that iterator and take the address of the result. For example: Code: int main() { func( &*iter); // ok }
Does the Compiler Always Create a Default Constructor? The compiler creates a default construtor only in the following situations: * When the class's base class defines the default constructor. * When the class of member objects defines default constructors. * When the class has a virtual function. * When the class has a virtual base class. So for the following class, the compiler does not create a defalut constructor if you do not define one: Code: class test { public: void show(); void get(int, char*, float); private: int h, char* ch; float f; };
The #error Preprocessor Directive During the preprocessing phase, you can report errors by using the #error preprocessor directive. For example, suppose you have a program that uses 64-bit integers. This program has to be ported to various platforms. Since C++ doesn't define a standard 64-bit int type yet, each compiler uses a different type, and some compilers don't support 64-bit integers at all. A portable program can use the following preprocessor directives to make sure that the use of 64-bit integers is transparent to the target compiler. If the target compiler doesn't support 64-bit integers, the #error directive causes it to produce a diagnostic message that includes a user-supplied string and stops the compilation process: Code: #if defined((__BORLANDC__) || defined(__VISUALC32__)) # define INT64 __int64 // then use the __int64 type #elif defined(__GNUC__) // GCC doesn't support __int64 # define INT64 long long // but uses 'long long' instead #else # error “Unsupported platform; aborting” #endif
How the compiler differentiates delete[] and delete? [thread=899]How the compiler differentiates delete[] and delete?[/thread]
function pointer problem Hello....... In the given code I want to use only one function pointer which can call two different type of function .............is it possible ................if yes then how ??? main() { // ( )(* fun_point)( ); int fun1(int,int); char fun2(char,char); }
[COMMENT]sandesh, do not jump into any thread with your query or else you will not see any responses as the visibility of your query is very less. Try creating a new thread for your query if its not related to the thread you have posted into.[/COMMENT]
i think this is also a suitable tip which can be put in this thread.. always do comparision by putting the constant on the left hand side of the exspression. e.g. Code: if (0 == toCompareVariable) { /*anything*/ } is a better programming practice than Code: if (toCompareVariable == 0) { /*anything*/ } this way even if someone do a typo and write if (0 = toCompareVariable) ..the compiler will produce an error on compilation itself..and thus we are not supposed to scratch our head finding where is code going wrong in case of if (toCompareVariable = 0)