http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/notes/index.html
http://cppreference.com/ http://www.cplusplus.com/ http://aszt.inf.elte.hu/~gsd/halado_cpp/index.html
http://www.cs.uu.nl/wiki/bin/view/Techno/ProgrammingLanguageTheoryTextsOnline#Obligatory_plea http://www.strchr.com/links?rev=1257040937
http://www.cs.bell-labs.com/cm/cs/pearls/code.html
http://cpp.snippets.org/browser.php
http://c.snippets.org/browser.php
http://www.relisoft.com./cpp.html
http://www.ddj.com/cpp/ http://www.ddj.com/cpp/archives.jhtml
Danny Kalev:
http://www.devx.com/cplus/10MinuteSolution
http://www.informit.com/guides/guide.aspx?g=cplusplus
http://www.gotw.ca/gotw Herb Sutter
http://ddj.com/cpp/206904716/ random number generator
Local files:
Q&A
HerbShields_CPP_CookBook
CPP_TimeSavingTechniques
ProgrammingParadigms.pdf
http://en.wikibooks.org/wiki/Category:Optimizing_C%2B%2B Optimizing C++
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms C++ Idioms
Excellent open-source libraries
String library: http://bstring.sourceforge.net/
XML http://www.grinninglizard.com/tinyxml/
code analysis: http://www.cppdepend.com/
http://www.mobile-mir.com/cpp/ class and h file dependency viewer
http://www.pantheios.org/ Logging API
struct a b = {0}; //struct initialization
rn = rand() % b; //random number in {0-b} interval; b < RAND_MAX
rn = rand() % (b - a + 1) + a; // {a-b} interval
Predefined macros in C++ compilers: http://predef.sourceforge.net/
http://msdn.microsoft.com/en-us/library/b0084kay.aspx
#if defined(_WIN32) || defined(_WIN64)
// C4290 - the compiler ignores exception specifications
#pragma warning(disable: 4290)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(__unix) || defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <cerrno>
#endif // _WIN32 || _WIN64
Useful macros: http://acm.mipt.ru/twiki/bin/view/Algorithms/
/* macros.h */
typedef vector< int > vi;
typedef vector < vector<int> > vii;
/* forall macro for GCC: */
#define forall(i, v) for( typeof(v.begin()) i = v.begin(); i != v.end() ; i++ )
/* forall macro for others */
#define forall2(i, v, type) for( type::iterator i = v.begin(); i != v.end() ; i++ )
#define all(v) v.begin(),v.end()
#define loop(i, n) for(int i = 0; i < n; i++)
#define pb push_back
#define sz(v) v.size()
#define belongs(x, c) (find((c).begin(), (c).end(), x) != (c).end())
// operator EQUAL for floating point.
#define EPS 1e-7
#define LEPS 1e-7
typedef long double ldouble
template<typename T> inline bool eq(T a, T b) { return a == b; }
inline bool eq(double a, double b) { return fabs(a-b) < EPS; }
inline bool eq(ldouble a, ldouble b) { return fabsl(a-b) < LEPS; }
inline bool eq(double a, ldouble b) { return fabsl(ldouble(a)-b) < EPS; }
inline bool eq(ldouble a, double b) { return fabsl(a-ldouble(b)) < EPS; }
template<typename T1, typename T2>
inline bool eq(T1 a, T2 b) { T1 _b = b; return eq(a, _b); }
extern "C" void foo(int i);
will allow the function to be implemented in a C module, but allow it to be called from a C++ module.
The trouble comes when trying to get a C module to call a C++ function (obviously C can't use C++ classes) defined in a C++ module. The C compiler doesn't like extern "C".
So you need to use this:
#ifdef __cplusplus
extern "C" {
#endif
void foo(int i);
#ifdef __cplusplus
}
#endif
Now when this appears in a header file, both the C and C++ compilers will be happy with the declaration and it could now be defined in either a C or C++ module, and can be called by both C and C++ code.
VOLATILE keyword
http://www.drdobbs.com/cpp/184403766
http://blog.regehr.org/archives/28
__inline is non-standard. it's usually a compiler extension which forces inlining, not hints it. inline
http://www.codelite.org/ http://www.ultimatepp.org/ http://www.codeblocks.org/
SQLite; anything out of Bell Labs is a good
http://code.google.com/p/v8/ JavaScript Engine
http://siag.nu/dwatch/ Daemon Watch t watches over other programs and performs actions based on conditions specified
vsftpd - secure and clean C code.
Postfix
http://fara.cs.uni-potsdam.de/~jsg/json_parser/JSON_parser.c
Games
http://www.suddenpresence.com/sgade/
http://wiki.xmms2.xmms.se/wiki/Main_Page
carmack's game engine code
Ogre (the graphics engine) is very decently designed and written C++ library
http://www.ogre3d.org/2009/09/23/game-engine-architecture-by-jason-gregory
libpqxx Postgress Driver
http://www.viva64.com/articles/20_issues_of_porting_C++_code_on_the_64-bit_platform.html
Platform-independent Datatype Widths
When writing dually-targeted code, it is important to clearly define which objects should have a fixed width, regardless of the target architecture. Fixed-width datatypes may be required in the following cases:
Reading data from a network connection
On-disk data that was written by a 32-bit application
Interfacing with certain binary standards
For such fixed-width datatypes, use the standard typedefs defined in <inttypes.h>:
int8_t int16_t int32_t int64_t //signed
uint8_t uint16_t uint32_t uint64_t //unsigned
Strictly speaking, <inttypes.h> is a C99 header. However, most C++ compilers nowadays support it.
C and C++ define standard typedefs such as size_t, ptrdiff_t, fpos_t, time_t, etc., that abstract the underlying type of an object, thereby enabling the compiler to map them to the suitable native datatype automatically. Always use these typedefs in dually-targeted code. Take for example size_t. In ILP32 it's defined as 32-bit unsigned integer. However, in LP64 it's defined as an unsigned 64-bit integer.
template <class T>
inline void Swap(T &x, T &y)
{
T w = x;
x = y;
y = w;
}
Adding text to the end of file
#include <iostream>
#include <fstream>
int main(void) {
std::ofstream outfile;
outfile.open("test.txt", std::ios_base::app);
outfile << "Data";
outfile.close();
return 0;
}
operators that cannot be overloaded:
sizeof, ., .*, .->, ::, ?:
Goal: to force cout<< to show the object in human friendly way:
student st("Bill Jones", "Zoology"); // create instance
cout<<st; // display student's details
First, you need to overload the operator << of class ostream (note that cout is an instance of ostream).
Finally, the overloaded operator should return the ostream object after the members have been inserted to it. This will enable you to chain several objects in a single cout statement:
student s1, s2;
cout<<s1<<s2; // chaining multiple objects
The insertion operations and the return statement can be accomplished in a single statement:
ostream& operator << (ostream& os, const student& s)
{
return os<<s.get_name()<<'\t'<<s.get_department()<<endl;
}
http://gethelp.devx.com/techtips/cpp_pro/10min/10min1100.asp
http://gethelp.devx.com/techtips/cpp_pro/10min/2001/august/10min0801-3.asp
bool little_endian(){
unsigned int ii = 0x01;
if (*(unsigned char *)&ii == 0x01)
return(true);
else
return(false);
}
// Definition of the Error log function.
#include <ostream.h>
void LogError(char * fname, int lnr)
{
cout << "Error in file: " << fname;
cout << " on line number: " << lnr << endl;
}
~
// Each file will pass its own name and line number.
void somefunct(void)
{
if (error) LogError(__FILE__,__LINE__);
}
// In the class header file.
#include <ostream.h>
char anyCompilationDate[] = __DATE__;
char anyCompilationTime[] = __TIME__;
class Any
{
public:
void SourceInfo(void)
{
cout << "Compiled at: ";
cout << anyCompilationDate << " " << anyCompilationTime << endl;
}
};
int mid =(low + high) / 2;
Code above fails for large values of the int variables low and high. Specifically, it fails if the sum of low and high is greater than the maximum positive int value (231 - 1). The sum overflows to a negative value, and the value stays negative when divided by two. In C this causes an array index out of bounds with unpredictable results. In Java, it throws ArrayIndexOutOfBoundsException.
This bug can manifest itself for arrays whose length (in elements) is 230 or greater (roughly a billion elements).
So what's the best way to fix the bug? Here's one way:
int mid = low + ((high - low) / 2);
Probably faster, and arguably as clear is:
int mid = (low + high) >>> 1;
In C and C++ (where you don't have the >>> operator), you can do this:
mid = ((unsigned) (low + high)) >> 1;
#include <stdio.h>
#include <time.h>
long F(unsigned int n){
return n <= 1 ? n : F(n-1) + F(n-2);
}
int main(){
time_t begin, end;
long res;
for(int n = 0; n < 40; n++) {
time(&begin);
res = F(n);
time(&end);
printf("%-3i\t%-9li\t%-20.3f\n",n,res,difftime(end,begin));
}
return 0;
}
long F(unsigned int n) {
long F_1 = 1, F_2 = 0, F_cur;
if(n <= 1)
return n;
for(unsigned int k = 2; k <= n; k++){
F_cur = F_1 + F_2;
F_2 = F_1;
F_1 = F_cur;
}
return F_cur;
}
You can enforce this compile-time constraint by declaring the destructor as a private member:
class HeapOnly { private: ~HeapOnly();//auto and static objects are disabled public: //.. };
How does this work? The compiler implicitly invokes the destructors of automatic and static objects when they go out of scope or when the program terminates, respectively. If the destructor isn't public, you get a compilation error, which is exactly what you want:
HeapOnly h1;//compilation error:
//"Destructor for 'HeapOnly' is not accessible"
int main
{
HeapOnly h2; // ditto
static HeapOnly h3; //ditto
}
You can create such objects on the free-store. This raises yet another question: how do you destroy them?
The solution is to delegate the destruction to another public member function:
class HeapOnly
{
private:
~HeapOnly();
public:
void destroy() {delete this;} //invoke the destructor
};
HeapOnly * p = new HeapOnly;
//..use p
p->destroy()
Admittedly, this technique isn't perfect because you still can't bind auto_ptr to such an object.
This time the problem is that auto_ptr's destructor can't delete p.
However, it shouldn't be difficult to write an elementary smart pointer class whose destructor contains:
p->destroy;
It's possible to define a class whose objects may be created on the stack or static memory but not on the free-store. For this purpose, override global new and delete by declaring them as non-public class members:
class AutoStatic
{
private:
void * operator new (size_t)
{return 0;} //dummy implementation
void operator delete (void*) {}
public:
//..
};
The compiler will use the overridden versions of new and delete to allocate and
destroy objects of this class.
Because these operators are inaccessible, any attempt to allocate such objects
on the free-store would cause compilation errors:
int main()
{
AutoStatic as; //fine
static AutoStatic as2; //fine
AutoStatic * p2= new AutoStatic; // error:
//'AutoStatic::operator new(unsigned int)'
//is not accessible
delete p2;//error:
//'AutoStatic::operator delete(void *)' is not
//accessible.
}
There is a loophole in this design, though. AutoStatic doesn't override the array versions of new and delete.
If you wish to disable dynamic allocation of AutoStatic arrays, override these operators as well:
class AutoStatic
{
private:
//override global new[] and delete[]
void * operator new [](size_t);
void operator delete [] (void*);
//..
};
Design Refinements
In cross-platform code, you should provide dummy definitions for the overriding new
and delete because some implementations may call them implicitly from constructors and destructors.
Notice, also, that in a class hierarchy, a derived class uses the overridden new and
delete of its base class, unless it declares its own overriding versions of these operators.
A Walk Down Memory Lane
Seasoned programmers can find ways to bypass the constraints that I've shown here.
For example, one could use placement new to construct objects on a buffer that was allocated from the free-store.
However, a bullet-proof design isn't the issue here. Rather, the aim is to protect your
code from innocent human errors and to draw users' attention to the memory-usage policy of a given class.
In this respect, making a destructor non-public is sufficient for disabling static and automatic objects.
Similarly, declaring new and delete as private or protected class members is also an
effective mechanism for disabling free-store allocation.
const can replace #define for constants, and allows more checking by the compiler. This should work also in ANSI C.
const can also be used with pointers and strict prototyping to ensure that the data value is not changed when pointers are pased around. This involves using const twice, for example:
const char *const msg = "string";
The first const prevents the value "string" being changed. The second prevents the pointer "msg" being
reassigned to point somewhere else.
The big headache with this is that once started, const *must* be used in all function calls. Otherwise somewhere down the line a function withou the "const" will be assumed by the compiler (from its prototype) to be capable of changing the pointer or its value and the call will result in compile-time error.
This can be avoided with a (char *) cast in the function call, but if the function prototypes have const for all unchanged pointers/data, and if there is no cheating going on with casts the results should be much improved type checking of code.
const char *myPointer is a non constant pointer to constant data;
char *const myPointer is a constant pointer to non constant data.
A reference must always refer to some object and, therefore, must always be initialized; pointers do not have such restrictions. A pointer can be reassigned to point to different objects while a reference always refers to an object with which it was initialized.
Pointers support arithmetic on them, references don't
References provide ease to accessing members and you don't always need the '->' operator which can be a typing pain sometimes. Use references where you can, pointers where you have to.
'malloc()' allocates a bunch of bytes while 'new' does the allocation as well as has the responsibility of calling the constructor.
'malloc' returns 'NULL' on failure while 'new' throws an exception object of type 'std::bad_alloc'. (There exists a nothrow version of 'new', though)
'malloc' is the C way of dealing with the free store while 'new' is the C++ way.
Every call to 'malloc()' should be followed by a call to 'free()' while every call to 'new' should be followed by a call to 'delete'.
'free()' deallocates all bytes allocated by a prior 'malloc()' call (using the same pointer) while 'delete' makes a call to the destructor and then goes on with the deallocation.
There are array forms of 'new' and 'delete' while 'malloc()' and 'free()' do not (as the request is for a specific size of raw memory in bytes).
'free()' on 'NULL' pointers is not safe while 'delete' is.
http://www.onlamp.com/pub/a/onlamp/2006/05/04/smart-pointers.html
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=239
http://ootips.org/yonat/4dev/smart-pointers.html
http://www.ddj.com/cpp/184403837/
Every invocation of operator new must be followed by a matching delete, but under some circumstances memory leaks may still occur. When exceptions are thrown, the program's normal flow of control is diverted, thereby causing potential memory leaks. For example:
void g() //might throw
{
if (some_condition == false) throw X();
}
void func()
{
string * pstr = new string;
g(); //memory leak if g throws an exception
delete pstr; //unreachable code if g() throws
}
int main()
{
try{
func();
}
catch(...){}
}
When g( ) throws an exception, the exception-handling mechanism unwinds the stack: g( ) exits and control is transferred to the catch(...) block in main(). However, the delete statement in func( ) is not executed, and as a result, the memory owned by pstr leaks. Had we used a local automatic string object—rather than a dynamically allocated one—the leak would have been avoided:
{
string str; //local automatic object
g(); //no memory leaks
}
Still, many nontrivial data models and applications such as linked lists, STL containers, strings, database systems, and interactive applications must allocate memory dynamically, taking the risk of causing memory leaks in case of exceptions. The C++ Standardization committee was aware of this loophole and added a special class template to the Standard Library, namely std::auto_ptr, whose purpose is to smoothen the interaction between dynamic memory and exceptions. Auto_ptr ensures that objects allocated on the free store (i.e., objects allocated by operator new) are automatically destroyed and their memory is released when an exception is thrown.
they need to support pointer operations like dereferencing (operator *) and indirection (operator ->)
template <class T> class auto_ptr
{
T* ptr;
public:
explicit auto_ptr(T* p = 0) : ptr(p) {}
~auto_ptr() {delete ptr;}
T& operator*() {return *ptr;}
T* operator->() {return ptr;}
// ...
};
Auto_ptr is defined in the header <memory>. Like every other member of the STL it is declared in namespace std::. When you instantiate an auto_ptr object, you initialize it with a pointer to a dynamically allocated object like this:
#include <memory>
#include <string>
using namespace std;
void func()
{
auto_ptr<string> pstr (new string);
}
In the angle brackets, you specify the type of the object to which the auto_ptr points, string in this example. Following that is the name of the auto_ptr instance, pstr in this example. You initialize the instance with a pointer to a dynamically allocated object. Note that you can only use auto_ptr's copy constructor for that purpose. The following, on the other hand, is illegal:
auto_ptr<string> pstr = new string; //compilation error
Auto_ptr is a template. Therefore, it's completely generic. It can point to any type of object, including fundamental types:
auto_ptr<int> pi (new int);
Once you have instantiated an auto_ptr and initialized it with the address of a dynamically allocated object, you use it as if it were an ordinary pointer to that object:
*pstr = "hello world"; //dereference and assign
pstr->size(); //call a member function
This is possible because auto_ptr overloads the operators &, * and ->. Don't let the syntax mislead you, though: pstr is an object, not a pointer.
How does auto_ptr solve the memory leak problem that we previously saw? The destructor of auto_ptr automatically destroys the dynamically allocated object bound to it. In other words, when the destructor of pstr executes, it deletes the pointer to string that was created during pstr's construction. You must never delete an auto_ptr since it is a local object, and as such, its destructor is invoked automatically. Let's look at a revised version of func() that uses auto_ptr:
void func()
{
auto_ptr<string> pstr (new string);
g(); //pstr is destroyed automatically if g() throws
}
C++ guarantees that objects with automatic storage type are destroyed during the stack unwinding process. Therefore, if g() throws an exception, the destructor of pstr will execute before control is transferred to the catch(...) block in main(). Now, since pstr's destructor deletes the pointer to string to which it is bound, no memory leaks occur. To conclude, auto_ptr provides the automation and safety of a local object when using a dynamically allocated object.
AVOIDING COMMON PITFALLS WITH AUTO_PTR
As convenient as auto_ptr may seem, there are some pitfalls that you should avoid when using it. First, never use auto_ptr objects as elements of STL containers. The C++ Standard explicitly forbids this and you may encounter undefined behavior (for reasons that we will not discuss here).
Another common pitfall is using an array as an auto_ptr argument:
auto_ptr<char> pstr (new char[12] ); //array; undefined
Remember that whenever you're using array-new, you need to use delete [] to properly destroy that array. However, auto_ptr's destructor invokes only non-array delete. Consequently, the array is not properly destroyed and the program's behavior is undefined. To summarize, auto_ptr should only hold a pointer to a single object that was allocated by new.
UTF-8: strings which contain only 7-bit ASCII characters have the same encoding under both ASCII and UTF-8
UTF-16
UTF-32
wchar
typedef unsigned short wchar_t ; signed 32-bit integer
strlen(s) function always counts the number of bytes
The number of characters can be counted in C in a portable way using
mbstowcs(NULL,s,0)
C++ by default doesn't initialize automatic variables. Consequently, uninitialized auto variables and aggregates have an indeterminate value.
C++ allows you to use 0 as a universal initializer for fundamental types, including pointers, pointers to functions and even pointers to members. Therefore, you may initialize temp like this:
bool temp=0; // 0 is converted to 'false'
Likewise, you may initialize all pointer types like this:
employee *p=0; //converted to NULL
void (*pfunc)(int)=0; //pointer to function
void (A::*pfunc)(int)=0; //pointer to member function
In fact, you are advised to use plain 0 instead of NULL in pointer initializations.
Syntactically, initializations look like ordinary assignments. However, there are substantial differences between the two. Conceptually, an initialization takes place at compile time whereas an assignment takes place at runtime. More importantly, you are allowed to initialize an array or a an aggregate (I will discuss aggregates shortly) but you cant assign to them:
char name1[5]="John"; //OK, initialization
char name2[5];
name2= "John"; //compilation error: assignment to an array
When initializing an array, you are allowed to use fewer initializers than the number of its elements (the opposite, however, is forbidden). It is guaranteed that the remaining elements are default-initialized in this case. For example, in the following expression, the array num has five elements but only the first three have explicit initializers:
int num[5]={0,1,2};
The elements num[4] and num[5] are automatically initialized to 0 in this case. Thus, to zero-initialize a large array you can provide a single initializer and let the compiler take care of the rest:
double results[500]={0.0}; //the remaining 499 elements
// are initialized to 0.0 as well
This form has the same effect:
double results[500]={0};
Or, if you're using a char array:
char URL[2048]={0}; //all elements are initialized to '\0'
If there are fewer initializers than the number of members, the remaining members are default-initialized:
struct Person
{
int age;
char name[20];
char address[100];
char occupation[50];
};
Person p={25, "Phileas Fogg", "Saville Row, W1 London"};
In this case, the elements of the array occupation are zero-initialized because no explicit initializer was provided for this member. Just as with arrays, you can easily zero initialize all the members of a struct like this:
Person p={0};
You're probably wondering whether this would work if the first member werent a fundamental type, say:
struct Book
{
char title[200];
char author[200];
int page_count;
};
Yes, it would:
Book b={0};
Remember that aggregate initialization rules are recursive: the initializer 0 is treated as the initializer of the first member of Book, which is an array. As previously noted, when an array's initialization list contains fewer initializers than the number of its elements, the remaining elements are zero-initialized. The literal 0 first initializes the first element of the array title, letting the compiler zero-initialize all the remaining elements. Because the initialization list of b doesn't provide explicit initializers for the rest of its members, these are zero-initialized as well.
Now suppose you want to declare an array of Book objects. The same form of initialization zero-initializes every element of the array:
Book arr[20] ={0};
Remember, it doesn't matter if you change the definition of Book later, say by adding more data members to it, or if you change the size of the array. The ={0}; initializer ensures that every member is properly initialized.
//Old stile:
Employee::Employee(String name, String designation)
{
m_name = name;
m_designation = designation;
}
/* === Optimized Version === */
Employee::Employee(String name, String designation): m_name(name), m_destignation (designation)
{
}
Mandatory Initialization
const members, references, and sub-objects (i.e., embedded objects and base classes) whose constructors take arguments necessitate a member initialization list. For example, a class that has a data member of type std::vector can pass an argument to its constructor like this:
class Thing
{
private:
int & ref; // reference member
const int MAX; // const member
vector arr;
public:
Thing(int& r) : ref(r), MAX(100), arr (MAX) {}
};
Notice that the member MAX serves as arr's initializer. This is perfectly legal. C++ ensures that members are initialized in the order of their declaration in the class. If you change the member initialization list to:
Thing(int& r) : arr(MAX), MAX(100), ref(r) {}
The members will still be initialized in the following order: ref, MAX, and arr. However, pay attention to the members' order inside the class. Doing something like this causes unpredictable results at runtime:
class BadThing
{
private:
int & ref;
Array arr; //wrong, should appear after MAX
const int MAX;
};
Constructors cannot be virtual.
A class must have a virtual destructor if it meets both of the following criteria:
You do a delete p.
It is possible that p actually points to a derived class.
Unlike ordinary member functions, a virtual destructor is not overridden when redefined in a derived class. Rather, it is extended: the lower-most destructor first invokes the destructor of its base class and only then, it is executed. Consequently, when you try to declare a pure virtual destructor, you may encounter compilation errors, or worse: a runtime crash. However, there's no need to despair--you can enjoy both worlds by declaring a pure virtual destructor without a risk.
//Interface.h file
class Interface {
public:
virtual ~Interface() = 0; //pure virtual destructor declaration
};
Somewhere outside the class declaration, the pure virtual destructor has to be defined like this:
//Interface.cpp fileInterface::~Interface()
{} //definition of a pure virtual destructor; should always be empty
protected destructor is used to prohibit from the memory allocation on stack or in the static data segment
and from the explicit deallocation by delete.
I.e. an object can be created on the heap but delete cannot be called for its pointer.
Practical use of the protected destructor (usually it's also virtual):
base classes with object count variable
classes used in the environment with memory garbage collection
any other classes where explicit object deletion is not acceptable
class TestClass
{
public:
TestClass() {}
void Release()
{
//whatever required
delete this;
}
protected:
virtual ~TestClass() {}
};
int main(int argc, char** argv[])
{
// TestClass tc; // gives error C2248: 'TestClass::~TestClass' : cannot access
// protected member declared in class 'TestClass'
TestClass* pTC = new TestClass;
// delete pTC; // gives the same error
pTC->Release();
return 0;
}
never throw an exception from a destructor
are implemented using a table of function pointers, called the vtable. There is one entry in the table per virtual function in the class. This table is created by the constructor of the class. When a derived class is constructed, its base class is constructed first which creates the vtable. If the derived class overrides any of the base classes virtual functions, those entries in the vtable are overwritten by the derived class constructor. This is why you should never call virtual functions from a constructor: because the vtable entries for the object may not have been set up by the derived class constructor yet, so you might end up calling base class implementations of those virtual functions
Declare local functions as "static" then possible
The volatile keyword is used to indicate a variable whose value might change at any moment. The keyword is used for variables such as memory -mapped I/O devices or in real-time control applications where variables can be changed by an interrupt routine. Look here http://www.airs.com/blog/archives/154
/*
** rounding macros by Dave Knapp, Thad Smith, Jon Strayer, & Bob Stout
*/
#ifndef ROUND__H
#define ROUND__H
#include <math.h>
#if defined(__cplusplus) && __cplusplus
/*
** Safe C++ inline versions
*/
/* round to integer */
inline int iround(double x)
{
return (int)floor(x + 0.5);
}
/* round number n to d decimal points */
inline double fround(double n, unsigned d)
{
return floor(n * pow(10., d) + .5) / pow(10., d);
}
#else
/*
** NOTE: These C macro versions are unsafe since arguments are referenced
** more than once.
**
** Avoid using these with expression arguments to be safe.
*/
/*
** round to integer
*/
#define iround(x) floor((x) + 0.5)
/*
** round number n to d decimal points
*/
#define fround(n,d) (floor((n)*pow(10.,(d))+.5)/pow(10.,(d)))
#endif
#endif /* ROUND__H */
Use forward class declarations where possible to avoid unnecessary compilation dependencies.
The class B in below only uses pointers or references to A, so I can get away with a forward declaration.
However, if I use an A member function or variable, or if I have an object of type A--and not just a pointer or reference to onein my definition for the class B,
suddenly my forward declaration is insufficient.
// myheader.h
#ifndef MYHEADER_H_ _
#define MYHEADER_H_ _
class A; // No need to include A's header
class B {
public:
void f(const A& a);
// ...
private:
A* a_;
};
#endif
PIMPL idiom http://www.devx.com/cplus/Article/28105/0
void caller(void(*p)())
{
p(); // call the bound function
}
void func();
int main()
{
p = func;
caller(p); // pass address of func to caller
}
The Standard Library defines several useful function objects that can be plugged into STL algorithms. For example, the sort() algorithm takes a predicate object as its third argument. (A predicate object is a templatized function object that returns a Boolean result). You can pass the predicates greater<> or less<> to sort() to force a descending or ascending sorting order, respectively:
#include <functional> // for greater<> and less<>
#include <algorithm> //for sort()
#include <vector>
using namespace std;
int main()
{
vector <int> vi;
//..fill vector
sort(vi.begin(), vi.end(), greater<int>() );//descending
sort(vi.begin(), vi.end(), less<int>() ); //ascending
}
The C++ standard now states that the operator new should throw an exception of type std::bad_alloc when it fails, rather than returning a NULL pointer. A program that calls new either directly or indirectly (for example, if it uses STL containers that in turn allocate memory using new) must contain an appropriate handler to catch a std::bad_alloc exception. Otherwise, whenever new fails, the program will abort due to an uncaught exception. The exception-throwing policy also implies that testing the result of new is completely useless.
void f(int size) //standard-conforming usage of new
{
char *p = new char [size];
//...use p safely
delete [] p;
return;
}
#include <stdexcept>
#include <iostream>
using namespace std;
const int BUF_SIZE = 1048576L;
int main()
{
try
{
f(BUF_SIZE);
}
catch(bad_alloc& ex) //handle exception thrown from f()
{
cout<<ex.what()<<endl;
//...other diagnostics and remedies
}
return -1;
}
Under some circumstances, throwing an exception is undesirable. The standardization committee was aware of this problem and added an exception-free version of new to C++ that returns a NULL pointer in the event of a failure, rather than throwing a std::bad_alloc exception. This version of new takes an additional argument of type const std::nothrow_t& (defined in the header <new>) and comes in two flavors: one for scalar new and another for new[]:
//exception-free versions of new and new[] defined in the header <new>
void* operator new(std::size_t size, const std::nothrow_t&) throw();
void* operator new[](std::size_t size, const std::nothrow_t&) throw();
The exception-free new is also called nothrow new. It's used as follows:
#include <new>
#include <string>
using namespace std;
void f(int size) // demonstrating nothrow new
{
char *p = new (nothrow) char [size]; //array nothrow new
if (p == 0)
{
//...use p
delete [] p;
}
string *pstr = new (nothrow) string; //scalar new
if (pstr == 0)
{
//...use pstr
delete [] pstr;
}
return;
}
const int BUF_SIZE = 1048576L;
int main()
{
f(BUF_SIZE);
return 0;
}
The literal 0 is of type int. However, it can be used as a universal initializer for every fundamental datatype. Zero is a special case in this respect because the compiler examines its context and automatically casts accordingly. For example:
void *p = 0; //zero is implicitly converted to 'void *'
float salary = 0; // 0 is cast to a float
char name[10] = {0}; // 0 cast to a '\0'
bool b = 0; // 0 cast to 'false'
void (*pf)(int) = 0; // pointer to a function
int (C::*pm) () = 0; //pointer to a class member
An uninitialized pointer has an indeterminate value. Such a pointer is often called a wild pointer. It's almost impossible to test whether a wild pointer is valid, especially if it's passed as an argument to a function. For example:
void func(char *p );
int main()
{
char * p; //dangerous: uninitialized
//...many lines of code; p left uninitialized by mistake
if (p) //erroneously assuming that a non-null value indicates
//a valid address
{
func(p); // func has no way of knowing whether p
//has a valid address
}
return 0;
}
Even if your compiler initializes pointers automatically, it's best to initialize them explicitly to ensure code readability and portability.
As noted previously, POD objects with automatic storage have an indeterminate value by default. However, you can initialize automatic POD objects explicitly when necessary. One way to initialize automatic POD objects is by calling memset(). However, there's a much simpler way to do it:
struct Person
{
long ID;
int bankAccount;
bool retired;
};
int main()
{
Person person ={0}; //ensures that all members of
//person are initialized to binary zeros
return 0;
}
This technique is applicable to every POD struct. It relies on the fact that the first member is a built-in datatype. The initializer zero is automatically cast to the appropriate built-in type. C++ guarantees that whenever the initialization list contains fewer initializers than the number of members, the rest of the members are initialized to binary zeros as well. Note that even if the definition of Person changes and members are added, all its members are still initialized. The same initialization technique is also applicable to local automatic arrays of fundamental type:
void f()
{
char name[100] = {0}; //all array elements are initialized to '\0'
float farr[100] = {0}; //all array elements are initialized to 0.0
int iarr[100] = {0}; //all array elements are initialized to 0
void *pvarr[100] = {0};//array of void *; all elements
//are initialized to 0
//...use the arrays
}
This technique works for any combination of structs and arrays:
struct A
{
char name[20];
int age;
long ID;
};
void f()
{
A a[100] = {0};
}
The result of applying delete to the same pointer after it has been deleted is undefined. Clearly, this bug should never happen. However, it can be prevented by assigning a NULL value to a pointer immediately after it has been deleted. Deleting a NULL pointer is harmless:
#include <string>
using namespace std;
void func
{
string * ps = new string;
//...use ps
if ( ps->empty() )
{
delete ps;
ps = 0; //safety measure
}
//...many lines of code
delete ps; // harmless
}
C-style cast:
const char *msg="don't touch!";
unsigned char *p=(unsigned char*) msg;
You cannot tell whether this was the programmer's intention or an oversight.
The New C++ Cast Operators
static_cast
const_cast
reinterpret_cast
dynamic_cast
you use static_cast to explicitly document a cast that would otherwise take place automatically:
bool b=true;
int n=static_cast<int> (b);
C++ automatically casts bool to int in this context so the use of static_cast in this case isn't necessary. However, by using it, programmers document their intention explicitly.
In other contexts, static_cast is mandatory. For example, when you cast void* to a different pointer type, as in the following example:
int n=4;
void *pv=&n;
int pi2 = static_cast<int *> (pv);
mandatory static_cast uses the information available at compile time to perform the required type conversion. Therefore, the target and the source might not be identical in their binary representation. Consider a float to int conversion. The binary representation of the floating number 10.0 is quite different from the equivalent integer value of 10. static_cast performs the necessary adjustments when casting one to the other.
The use of static_cast enables the compiler to catch programmers' mistakes such as this:
const char *msg="don't touch!";
unsigned char *p= static_cast<unsigned char*> (msg);
Error here: the compiler issues an error message indicating that the cast operation attempts to remove the const qualifier of msg -- something that the programmer probably didn't intend anyway.
The removal of const requires a special cast operator called const_cast. This operator may perform only the following operations:
-Remove the const and or volatile qualification;
-Add const and or volatile qualification.
For example
struct A
{
void func(){} // non-const member function
};
void f(const A& a)
{
a.func(); // error, calling a non-const function
}
Clearly, this is a design mistake. The member function func() should have been declared const in the first place. However, such code does exist in third-party libraries; when innocent programmers try to use it, they have to resort to brute force casts. To overcome this problem, you may remove the const qualifier of a and then call func() as follows:
A &ref = const_cast<A&> (a);
Trying to perform any other conversion with const_cast will result a compilation error. Remember also that while const_cast may remove the const qualifier of an object, this doesn't mean that you're allowed to modify it. In fact, trying to modify a const object causes undefined behavior. Therefore, use const_cast cautiously when it is used for the removal of const or volatile.
As opposed to static_cast, reinterpret_cast performs relatively dangerous and nonportable casts. reinterpret_cast doesn't change the binary representation of the source object. Therefore, it is often used in low-level applications that convert objects and other data to a stream of bytes (and vice versa). In the following example, reinterpret_cast is used to "cheat" the compiler, enabling the programmer to examine the individual bytes of a float variable:
float f=10;
unsigned char *p = reinterpret_cast <unsigned char*> (&f);
for (int j=0; j<4; ++j)
cout<<p[j]<<endl;
The use of reinterpret_cast explicitly warns the reader that an unsafe (and probably a nonportable) conversion is taking place. When using reinterpret_cast, the programmer -- rather than the compiler -- is responsible for the results.
One practical use of reinterpret_cast is in a hash function, which maps a value to an index in such a way that two distinct values rarely end up with the same index.
// compile with: /EHsc
#include <iostream>
// Returns a hash code based on an address
unsigned short Hash( void *p ) {
unsigned int val = reinterpret_cast<unsigned int>( p );
return ( unsigned short )( val ^ (val >> 16));
}
using namespace std;
int main() {
int a[20];
for ( int i = 0; i < 20; i++ )
cout << Hash( a + i ) << endl;
}
The primary purpose for the dynamic_cast operator is to perform type-safe downcasts. A downcast is the conversion of a pointer or reference to a class A to pointer or reference to a class B, where class A is a base class of B
-downcast i.e., casting a base class pointer or reference to a pointer or reference of a derived class
-crosscast in which the programmer converts a multiply-inherited object to one of its secondary base classes.