Contact:
Thorsten Gunkel
63456 Hanau
Germany
Mail
Vote to help me to improve this page!Did this page satisfy your expectations?
Last modified: 18-05-2008 15.06
See also
| Author |
Title |
| Bjarne Stroustrup |
The C++ Programming Language 3. Edition |
| Ulrich Breymann |
C++ Eine Einführung |
| Namir Clement Shammas |
C++ für Dummies |
09-12-2007 02.27
How programs are being startet
A short
overview about ELF and how programs are started in Linux.
18-05-2008 15.06
export CC=gcc-3.2 CXX=g++-3.2
06-08-2005 13.09
$ ulimit -c unlimited
$ gcc -g PRG
$ g++ -g PRG
$ ./PRG
- CRASH -
$ gdb PRG core
run
bt
up
down
print $VAR
break foo.cpp:301
delete 1
DDD - Data Display Debugger
valgrind
valgrind --leak-check=yes --show-reachable=yes ./MYPROGRAM
memprof
alleyoop
GNU gprof
g++ -g -pg foo.cpp -o foo.run
./run
gprof foo.run gmon.out | less
gprof foo.run gmon.out -f Foo::myfunction | less
doxygen
doxygen (x)emacs
C-c d f
C-c d ;
23-12-2006 12.47
#ifndef _myh1_h_
#define _myh1_h_
#include <iostream>
namespace my_program {
extern int global1;
}
#endif /* _myh1_h_ */
#include <GL/glut.h>
#include "cg3_ex1.h"
using namespace std;
namespace my_program
{
int global1 = 5;
float global2 = 6.0;
/**
* comment here
*/
void foo()
{
}
}
int main(int argc, char **argv)
{
using namespace my_program;
return 0;
}
In C++ try to avoid them.
#define FOO blabla
#define BAR(a,b) 1: a 2: b
(no ; at the end of the line necessary, FOO and BAR are just replace everywhere).
Don't compile certain areas:
#define VERSION1
...
#ifdef VERSION1
...
#elseif
...
#endif
Don't forget parenthesis
#define SQUARE1(a) a*a
#define SQUARE2(a) (a)*(a)
SQUARE1(1+2) // 1+2*1+2
SQUARE2(1+2) // (1+2)*(1+2)
26-10-2006 06.14
int x; x=5; cout << x; // 5
int& r=x; cout << r; // 5
int* y; y=&x; cout << y; // 5 if x is still valid, trouble otherwise
int* y; y=new int; delete y;
int* z; z=y; cout << z // 5
x=*z; cout << x // 5
int * ptr2=(int*)malloc(155*sizeof(int));
for (int i=0; i<155; i++) {
std::cout << ptr2[i];
}
#include <limits>
#include <iostream>
int main()
{
using namespace std;
numeric_limits<int> INT;
...
cout << "INT Min: " << INT.min() << " Max: " << INT.max() << " EP: " << INT.epsilon() << endl;
...
}
|
int |
uint |
short |
ushort |
long |
ulong |
float |
double |
ldouble |
| min i486 |
-2147483648 |
+0 |
-32768 |
+0 |
-2147483648 |
+0 |
1.17549e-38 |
2.22507e-308 |
3.3621e-4932 |
| min amd64 |
-9223372036854775808 |
| max i486 |
+2147483647 |
+4294967295 |
+32767 |
+65535 |
+2147483647 |
+4294967295 |
3.40282e+38 |
1.79769e+308 |
1.18973e+4932 |
| max amd64 |
+9223372036854775807 |
+18446744073709551615 |
| epsilon i486 |
0 |
1.19209e-07 |
2.22045e-16 |
1.0842e-19 |
| epsilon amd64 |
In C abfangen ob die Integer Grenzen überschritten wurden
Value of x can't be changed
const int x=4;
Pointer points to a value which can't be changed
int const * z;
const int * z;
Const pointer, value can be changed
int * const z;
Pointer and value are const
int const * const z;
const int * const z;
Methods which don't modify class variables should be declared const
class Foo {
public:
int getX() const {
return this->x;
}
}
Sometime you might want to modify an unimportant class variable in a const method, e.g. you might want to count how often a get method was accessed:
class Foo {
unsigned int statistic_access_counter;
public:
int getX() const {
this->statistic_access_counter++; // Error!
return this->x;
}
}
This won't be allowed by your compiler
You can either use const_cast to get full write access:
class Foo {
unsigned int statistic_access_counter;
public:
int getX() const {
Foo * tmp=const_cast<Foo *>(this);
tmp->statistic_access_counter++;
return this->x;
}
}
or (which is the better solution) mark the unimportant variables which might to modified in const methods:
class Foo {
mutable unsigned int statistic_access_counter;
public:
int getX() const {
this->statistic_access_counter++;
return this->x;
}
}
int * ptr2=(int*)malloc(155*sizeof(int));
for (int i=0; i<155; i++) {
std::cout << ptr2[i];
}
int a[3]; // a[0], a[1], a[2]
int b[]= {10,11,42};
char c[]= {'a','z','m'};
int d[2]={10,11,42}; // Error!
int d[7]={10,11}; // a[2]==a[3]==...==a[6]==0
b={10,11,42}; // Error
Tricky example how to copy a 0 terminated c string.
mystringcopy(char * a, const char * b) {
// A
while(*b!=0) {
*a=*b;
a++;
b++;
}
*a=0;
// B
while( (*a++=*b++) != 0 );
// C
while( *a++=*b++ );
}
Variant B and C use the fact that a=b returns b.
char c[3];
c[0]='a';
c[1]='b';
c[2]=0;
char * c1=new char[3];
char * c2="ab";
int i=1242;
int len=(int)floor(log(i)/log(10));
char c[16+l+1];
snprintf(c,sizeof(c),"This is my int: %d",i);
c[sizeof(c)-1]=0;
char c[5]="1242";
int i=atoi(c);
char *p, *s;
s = "20y";
int i2 = strtol(s,&p,0); // i2:20 p:y
string str2("abc");
C++ strings
enum { FOO, BAR };
enum myenumtyp { FOO, BAR };
typedef enum { FOO, BAR } myenumtyp;
enum myenumtyp { FOO=0, BAR=1 };
Enumerations are often better than normal constants because the compiler can check if you didn't miss one in e.g., a switch statemant.
27-01-2007 06.37
Normal function which returns a value and copies the value of the parameter before using it:
int foo(int x) {
return x++;
}
This does the same as the previous example. However the parameter is a (read only) reference to the original variable. This is faster for large objects:
int foo(const int& x) {
return x++;
}
Here the parameter can be changed and all changes will persist when the function terminates:
void foo(int& x) {
x++;
}
Return by reference. Important:
Store the result into a reference variable, otherwise you get a copy.
int & foo() {
return x;
}
int a=foo(); // :-(
int & b=foo(); // :-)
First two normal functions:
int DoIt1 (float a, int b, int c)
{
return a+b+c;
}
int DoIt2 (float a, int b, int c)
{
return a*b*c;
}
class MyClass {
public:
int DoIt3(float a, int b, int c)
{
return a+b*c;
};
};
Define pointers for them:
int ( *foo)(float, int, int);
int (MyClass::*bar)(float, int, int)=&MyClass::DoIt3;
Assign the the pointers to the functions:
foo = DoIt1;
int result1 = foo(1.0, 2, 3);
int result2 = (*foo)(1.0, 2, 3);
foo = DoIt2;
int result3 = foo(1.0, 2, 3);
MyClass * f;
int result4 = f->DoIt3(1.0, 2, 3);
int result5 = (f->*bar)(1.0, 2, 3);
A pointer as a parameter:
void myfunc(int (*foo)(float, int, int))
{
int result = foo(1.0, 2, 3);
}
myfunc(&DoIt1);
myfunc(&DoIt2);
void foo(bool a, bool b=false);
The second parameter is optional, default is false
void foo(bool a ...);
As many bool parameters as you need (at least one), see <cstdarg> how to get the parameters.
02-11-2006 21.53
class MyClass : public MyParentClass
{
public:
MyClass();
MyClass(int x);
int my_method() const;
static int getTime();
protected:
int my_var;
private:
};
MyClass::MyClass() {
..
}
int MyClass::MyClass(int x) : MyParentClass(59)
{
...
}
int MyClass::my_method() const {
...
}
int MyClass::getTime() {
...
//in java super()
this is super() for c++
MyParentClass::getTime();
...
}
MyClass x(5);
MyClass * x=new MyClass(5);
Note that you need
exactly one additional definition of the static variables
outside the class.
If you implement a static method do not repeat the keyword static.
class MyOtherClass {
public:
MyOtherClass() {
z=0;
}
static int foo() {
return ( MyOtherClass::x + MyOtherClass::y );
}
int bar() {
return ( MyOtherClass::x + MyOtherClass::y + this->z );
}
protected:
static int y;
static int x;
int z;
};
// !!!
int MyOtherClass::x=0;
int MyOtherClass::y=0;
// !!!
int main() {
...
}
If you modify non-virtual methods in derivated classes you might be surprised that the method from the father class might be called. Evil if the the destructor method is one of these methods.
#include <iostream>
using namespace std;
class A {
public:
int foo() {
return 1;
}
virtual int bar() {
return 1;
}
//~A() { <------ Don't!
virtual ~A() {
//...
}
};
class B : public A {
public:
int foo() {
return 2;
}
virtual int bar() {
return 2;
}
//~B() {
virtual ~B() {
//..
}
};
int main() {
A a; B b; A * x; x=&b;
cout << a.foo() << a.bar() << endl; // 11
cout << b.foo() << b.bar() << endl; // 22
cout << x->foo() << x->bar() << endl; // 12
return 0;
}
| public: | Everyone |
| protected: | Only objects of this class + descendants |
| private: | Only class |
Try to make class variables private, methoden protected, avoid public.
Group different parts of the program in its own namespace.
namespace Foo {
double x;
double getX();
}
namespace Foo_1 {...};
namespace Foo_2 {...};
namespace MyFoo=Foo_2;
So you can even give a namespace a different name. Easy to switch between different namespaces.
How to access elements of different namespaces
int y=Foo::x;
using Foo::getX;
using Foo;
You can also use using to make the protected method of you parent class a public method of yourself
class A {
protected:
double getX();
};
class B : public A {
public:
using A::getX;
};
Foo a;
Foo b=a;
ruft den Copy Konstruktor auf:
Foo::Foo(const Foo& a);
If your object has pointers to memory which has to be freed in the destructor this may cause problems:
Foo a;
Foo b=a;
Foo c;
The destructor is only called for a and c, for b the copy constructor is called instead.
At the end the destructor for all of the is called and you may free memory twice.
If there is a matching constructor you can initialise an object via an assignment:
class complex {
public:
complex(double r, double i) {this->re=r; this->im=i;}
complex(double r) {this->re=r; this->im=0;}
private:
double re,im;
}
complex a=complex(2.3);
complex b=2.3;
class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};
A A
| |
B C
\ /
D
Now there are two different A objects. Better declare a virtual inheritance to A:
class A {};
class B : public virtual A {};
class C : public virtual A {};
class D : public B, public C {};
A
/ \
B C
\ /
D
FOO a;
BAR b=(BAR)a;
FOO * c;
BAR * d=(BAR *)c;
Assume we have the following hierarchy
class A {};
class B {};
class C : public A {};
class D : public B {};
class E : public C, public D {};
A B
| |
C D
\ /
E
And want to cast an object of the type A* to one of the type B*.
You can do that manually:
A * a;
C * c=(C*) a;
E * e=(E*)c;
D * d=e;
B * b=d;
Or with a dynamic_cast
B * b=dynamic_cast<B*>a;
This will fail of A has no virtual method with this error:
error: cannot dynamic_cast `a' (of type `class A*') to type `class B* ' (source type is not polymorphic)
static_cast is a bit faster, but has no checks if you're doing something reasonable. Avoid it.
Foo a;
Bar b;
if (typeid(a)==typeid(FOO)) ...
if (typeid(a)==typeid(BAR)) ...
if (typeid(b)==typeid(FOO)) ...
if (typeid(b)==typeid(BAR)) ...
28-10-2006 20.48
try {
...
throw(5);
...
throw(5.0);
}
// default catch, catch all
catch(int a)
{
}
catch(float b)
{
}
catch(...)
{
}
If possible list all exceptions you will throw:
void foo() throw();
void foo() throw(X,Y);
If another is thrown unexpected will be called.
Problem:
foo() {
...
fopen(FILE);
...
if (...) throw error1;
...
fclose(FILE);
...
}
If an exception is thrown the will needs to be closed. Complicate to not miss any case. Tricky solution: Write a class which will open the file in its constructor and closes the file in the destructor:
class X {
public:
X() { fopen(FILE); };
~X() { fclose(FILE); };
}
Now you can rewrite the example like this:
foo() {
...
X x;
...
if(...) throw error1;
...
}
Now the file will be closed whenever the object leave the scope (which will also happen when the exception is thrown).
The is already a generic object for this available: auto_ptr from <memory>.
Stack<int> data;
try
{
for(;;) { data.pop(); }
}
catch(data::Empty)
{
...
}
Instead to check in the for header when to stop just catch the exception. (Too) Tricky, better avoid it.
//#define NDEBUG
#include <cassert>
assert(a>0 && b<0);
26-10-2006 05.49
template <class Pairtype>
class Pair
{
template class Pair<int>;
template class Pair<double>;
public:
Pair();
Pair(Pairtype left, Pairtype right);
Pairtype get_left();
void set_left(Pairtype left);
protected:
Pairtype left;
Pairtype right;
};
}
template <class Pairtype>
Pair<Pairtype>::Pair(Pairtype left, Pairtype right)
{
this->left=left;
this->right=right;
}
template <class Pairtype>
Pairtype Pair<Pairtype>::get_left()
{
return left;
}
template <class Pairtype>
void Pair<Pairtype>::set_left(Pairtype left)
{
this->left=left;
}
Pairtype<int> foo;
07-09-2006 14.27
class tg {
public:
static tg& get_instance(void) {
return tg::my_instance;
}
private:
static tg my_instance;
tg() {
}
tg(const tg&);
tg& operator=(tg&);
};
tg tg::my_instance;
int main(int argc, char **argv)
{
tg& a = tg::get_instance();
}
06-08-2005 13.09
class MyClass {
public:
...
MyClass & operator+=(const MyClass & other);
}
friend bool operator< (const MyClass& a, const MyClass& b) {
return a.foo<b.foo;
}
std::ostream& operator<< (std::ostream& os, const MyClass& a) {
os << "Foo: " << a.foo << " Bar: " << a.bar << std::endl;
return os;
}
// ++i
MyInt MyInt::operator++() {
value+=1;
return value;
}
// i++
MyInt MyInt::operator++(int) {
MyInt rescue=value;
value+=1;
return rescue;
}
26-10-2006 06.11
vector <ContainerType> a;
vector <ContainerType>::iterator iter_a;
vector <ContainerType>::const_iterator constiter_b;
vector <ContainerType> c;
vector <ContainerType>::reverse_iterator inter_r;
iter_b=c.end();
iter_a=c.begin();
(*iter_a)=c.at(0);
while (iter_a!=c.end())
{
cout << *iter_a;
iter_a++;
}
if (c.end()!=c.begin()) {
iter_a=c.end();
do {
iter_a--;
cout << *iter_a << endl;
} while (iter_a!=c.begin());
}
for (iter_r=c.rbegin(); iter_r!=c.rend(); iter_r++) {
cout << *iter_r << endl;
}
for(iter_a=c.begin(),x=0;
iter_a!=c.end() && x<100;
iter_a++, x++
) {}
If you like to insert something in a container you need a reasonable iterator.
b.end() points behind the end of the container, b.begin() would overwrite elements.
Solution: back_insert_iterator
#include <vector>
#include <list>
#include <iostream>
using namespace std;
int main() {
vector<int> a;
vector<int> b;
a.push_back(1);
a.push_back(2);
a.push_back(3);
copy(a.begin(), a.end(), back_insert_iterator<vector< int > >(b));
// 1
// 2
// 3
for(vector<int>::const_iterator i=b.begin(); i!=b.end(); i++)
cout << *i << endl;
cout << endl;
list<int> myList;
back_insert_iterator< list< int > > myListIteratorBack(myList);
front_insert_iterator< list< int > > myListIteratorFront(myList);
myListIteratorBack=4;
myListIteratorBack=5;
myListIteratorFront=6;
// 6
// 4
// 5
for(list<int>::const_iterator i=myList.begin(); i!=myList.end(); i++)
cout << *i << endl;
cout << endl;
}
Try not to iterate through the container yourself
vector<int> a;
for(vector<int>::iterator i=a.begin(); i!=a.end(); i++) foo(*i);
instead use stl functions for that:
sort(a.begin(), a.end());
for_each(a.begin(), a.end(), foo);
The last one won't work with methods (only function). If you have a class:
class X {
public:
void draw();
}
and want to call a method of each element use a function for that:
vector<X *> data;
void foo(X * x) {
x->draw();
}
for_each(data.begin(), data.end(), foo);
There is already a function called
mem_fun for this:
for_each(data.begin(), data.end(), mem_fun(&X::draw));
List with useful functions:
functor
class mycomp {
public:
bool operator()(double x, double y) { return fabs(x) < fabs(y); }
};
vector<double> data;
sort(data.begin(), data.end(), mycomp());
30-10-2006 21.48
Skips the rest of the current loop run and starts the next one
for (int i=0; i<5; i++) {
std::cout << "\n";
std::cout << i << " ";
if (i==2) continue;
std::cout << i;
}
Output
0 0
1 1
2
3 3
4 4
Skips the whole loop
for (int i=0; i<5; i++) {
std::cout << "\n";
std::cout << i << " ";
if (i==2) break;
std::cout << i;
}
Output
0 0
1 1
2
Beside continue and break there is also goto! ;-)
goto foo;
...
foo:
...
if (a<=b) max=a; else max=b;
max=(a<=b) ? a : b;
| cout | #include <iostream> |
| std::cout << std::setw(8) << foo << std::endl; | #include <iomanip> |
| fabs(int) | #include <cstdlib> |
| fabs(float) | #include <cmath> |
29-10-2006 02.17
Assume you have the following small project:
new.cpp
#include "old.h"
class newClass
{
public:
int newClassMethod(int x) {
return proxy(x);
}
};
int main(int argc, char **argv) {
newClass newObject;
return newObject.newClassMethod(5);
}
old.h
int proxy(int x);
old.cpp
#include "old.h"
class oldClass
{
public:
int myold(int x) {
return 25;
}
};
int proxy(int x) {
oldClass oldObject;
return oldObject.myold(x);
}
In new.cpp there is an object of the newClass class which uses code from the file old.cpp. This project should compile without problems:
g++-2.95 -c old.cpp -o old.o
g++-2.95 -c new.cpp -o new.o
g++-2.95 old.o new.o -o myproject
Things get interesting if you have to compile old.cpp with g++-2.95 (e.g. because you don't have access to the sources of old.o to recompile it) and want to compile the rest with a newer compiler
g++-2.95 -c old.cpp -o old.o
g++-3.3 -c new.cpp -o new.o
g++-3.3 old.o new.o -o myproject
This will fail
new.o(.gnu.linkonce.t._ZN8newClass14newClassMethodEi+0xd): In function `newClass::newClassMethod(int)':
: undefined reference to `proxy(int)'
collect2: ld returned 1 exit status
because the
ABI between gcc-3.2 and the ABI of previous versions differ. However there is a way to circumvent this. Just offer in one of the files, which also has been compiled with an old version of the compiler, a C function which can be uses as a interface between both worlds. This works because the ABI only changed for C++ code and not for C code. Everything we have to do in our example is to declare this function as a C function:
old.h
extern "C"
{
int proxy(int x);
}
Now it can be used as an interface between both worlds.
However there are still problems if the new and the old files like to use for example the stl libs. This is how you can fix it:
Example project:
newClass.cpp,
newClass.h,
new.cpp ,
oldClass.cpp ,
oldClass.h,
old.cpp,
old.h.
First compile all the files with their matching compiler
g++-2.95 -c old.cpp -o old.o
g++-2.95 -c oldClass.cpp -o oldClass.o
g++-3.3 -c new.cpp -o new.o
g++-3.3 -c newClass.cpp -o newClass.o
Now combine all old .o files to one static file .o. This will show you how to do it:
g++-2.95 -v -static -r -o allOldStuff.o old.o oldClass.o
Be careful not to include the same file twice in the next step so remove some of the .o files from the command line until the next steps works without errors about duplicates. It may look like this:
/usr/lib/gcc-lib/i386-linux/2.95.4/collect2 -m elf_i386 -static -o allOldStuff.o -r -L/usr/lib/gcc-lib/i386-linux/2.95.4 old.o oldClass.o -lstdc++ -lm -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-linux/2.95.4/crtend.o /usr/lib/crtn.o
Everything that is left is to combine all new .o files against the .o you created from all the old files:
g++ -o MyProgram new.o newClass.o allOldStuff.o
Done :-)
Sadly it looks there are run-time problems with this solution.
06-09-2006 00.02
Thanks to
Richard Eckart for all the hints.
18-05-2008 15.06