Procedural: Variables, types, scopesTrail Index | References and Pointers | Dynamic Memory Dynamic Memory allocationThe existance of pointers allows you to access also parts of memory which is not pre-labeled, unlike a normal variable. /** * Pointers * * The message is: pointers are powerful, sometimes necessary, and dangerous. * Use the STL containers if you can. * * All the plain C libraries usually require pointers * for parameter passing, since C does not have references. * * Unfortunately ROOT and GEANT4 use pointers in many * completely unncessary cases. Beware. */ #include <iostream> using namespace std; struct DataPoint { double x,y,e; }; int main() { { /* * a const pointer to a modifiable structure */ DataPoint* const p1=new DataPoint; p1->x=2.; cout<< p1->x <<endl; //p1++; // not allowed: can't make it point to something else /* * copy the address, not the data */ DataPoint* p2=p1; p2++; // allowed, but what will it point to??? cout<< p2->x <<endl; // may crash, or just give something funny /* * a pointer to a const structure */ const DataPoint* p3=p1; cout<< p3->x <<endl; //p3->x=3.; // not allowed: *p3 is read-only /* * a const pointer to a const structure */ const DataPoint* const p4=p1; cout<< p4->x <<endl; delete p1; /* * Be careful: p1 will still contains the memory address, * but you MUST NOT USE IT !! * The same for p2,p3,p4 */ } { // runtime-length arrays int n=3*4; DataPoint* const p=new DataPoint[n]; /* * can be used to iterate on arrays, * not really useful, since it requires a double index! */ int i=0; for(const DataPoint* ip=p;i<n;ip++,i++) { cout<< ip->x <<endl; } /* * note the [] of this delete. * If you forget it, it will not free all allocated memory */ delete[] p; } { /* * More useful for char arrays, which are zero-terminated, * or other structures like linked lists which may use * similar end-of-structure special values. * But it's DANGEROUS - the terminator may be missing!! * Much better to use STL containers and iterators. */ char aString[]="a character array"; //aString[strlen(aString)]='?'; for (char* p=aString;*p!='\0';p++) { if (*p!=' ') cout<<*p; } cout<<endl; } } When working in C++, it is very important to follow the Resource acquisition is initialization rule: /** * Pointers and objects * * Mantra: "Resource acquisition is initialization" * * Each object must contain no more than one pointer; * in this way the automatic calling of the destructor takes care * of deallocation of memory even in the most catastrophic case * of failure to allocate the resource in the constructor. * * Of course, it is in principle possible to have more than one pointer * in an object, but it requies careful "manual" handling. */ #include <iostream> using namespace std; class BigContainer { int id; int* bigArray; public: BigContainer(int _id,int n) : id(_id),bigArray(NULL) { cout<<"BigContainer "<<id<<" c-tor 1\n"; bigArray=new int[n]; // can throw cout<<"BigContainer "<<id<<" c-tor 2\n"; } ~BigContainer() { cout<<"BigContainer "<<id<<" d-tor 1\n"; delete[] bigArray; cout<<"BigContainer "<<id<<" d-tor 2\n"; } }; class MyContainer { BigContainer c1,c2; public: MyContainer():c1(1,1000*1000),c2(2,1000*1000*1000) {} ; }; int main() { try { MyContainer c; } catch(...) {} ; cout<<"all is still fine...\n"; return 0; } ConclusionsThe basic message is: pointers are powerful, sometimes necessary, and most often dangerous. Memory pointers are an extremely simple and powerful construct, which is fundamental in C. But they are also easily abused and misused; which is the reason why many modern high-level programming languages like Java, Python, Ruby do not allow you to use pointers, at all. C++ allows you to use pointers, which consequently makes it very easy to utilise any C code library from C++, and makes C++ a viable choice also for those "system level" uses like Data Acquisition, where the interaction with hardware necessarily requires direct access to system memory. But C++ provides specialised alternatives like std::string, STL containers, and the powerful reference construct. For this reason it is important to learn first to use these high level constructs, and be able to use them as much as possible before resorting to use pointers and similar low-level constructs. The direct use of pointer does allow for some (very) small performance benefits compared to even the most appropriate use of high level constructs, but this is seldom a sufficient justification for the increased problems, especially in large codes. |