C++

Debugging in Release Mode

This information helped me a lot. Here I quote the answer:

In VS, right click your project, chose "Properties".

- Click the C/C++ node. Set Debug Information Format to C7 compatible (/Z7) or Program Database (/Zi).

- Expand Linker and click the General node. Set Enable Incremental Linking to No (/INCREMENTAL:NO).

- Select the Debugging node. Set Generate Debug Info to Yes (/DEBUG).

- Select the Optimization node. Set References to /OPT:REF and Enable COMDAT Folding to /OPT:ICF.

That's ripped directly from http://msdn.microsoft.com/en-us/library/fsk896zz.aspx

I do this all of the time and pretty much never debug
in debug mode anymore. As you know, many errors that occur
in a release build may not occur in a debug build (almost
certainly the errors that arise from invoking UB).

Also, I work on a project which uses a ton of image
processing and performs a lot of compression/decompression
of large images. Using a slow debug build is simply impractical.

Check whether an entry exists in std::map

// in map, count will return either 0 or 1
if (theMap.count(theKey))
{
    // it exists
}
else
{
    // it doesn't exist
}

Attention! If an entry in a std::map does not exist and you access it, it will silently generate an entry for that key! (normally setting the value for the key to 0 if it is a numeric value, or ”” if it is a string)

e.g.

std::map<int,float> myMap;
float tryingToGetAValueFromThatEmptyMap = myMap[123];
std::cout << "value=" << tryingToGetAValueFromThatEmptyMap << std::endl;

will output value=0

Erasing elements of a std::map while iterating

Using whatever data container, running through the elements and erasing one, normally invalidates iterating it further…

Be careful about this hint:

it = mymap.begin();
while (it != mymap.end()) {
   if (something)
      mymap.erase(it++);
   else
      it++;
}

Initialize a float to the smallest negative value

Use

float f =  -std::numeric_limits<float>::max();

and NOT (!)

float f =  std::numeric_limits<float>::min();

See here:

You can either use -FLT_MAX (or -DBL_MAX) for
the maximum magnitude negative number
and FLT_MAX (or DBL_MAX) for positive.
This gives you the range of possible float (or double) values.

You probably don't want to use FLT_MIN; it corresponds
to the smallest magnitude positive number that can be
represented with a float, not the most negative value
representable with a float.

FLT_MIN and FLT_MAX correspond to
std::numeric_limits<float>::min() and
std::numeric_limits<float>::max().

What's the difference between _tmain() and main() ?

Difference between pointers vs. references?

E.g. myClass* is a pointer to myClass, while myClass& is a reference to myClass.

  • a pointer can be re-assigned any number of times while a reference can not be reassigned after initialization
  • a pointer can point to NULL while reference can never point to NULL
  • you can't take the address of a reference like you can with pointers
  • there's no “reference arithmetics” (but you can take the address of an object pointed by a reference and do pointer arithmetics on it as in &obj + 5)

i.e. a pointer is more flexible (since it is a variable as well where you store the address of an object) than a reference (which is just the address of an object in memory that is fixed).

Reading/Writing binary data in C++

  • see this blog article which explains it quite well and suggests additionally a helper template function to do so
void Test::save(string fname)
{
    float testFloat = 1.23;
    string testStr = "This is my test string!";
 
    ofstream myfile;
    myfile.open ( fname, ios::out | ios::binary );
    myfile.write( (const char*) &testFloat, sizeof(testFloat) );
 
    int strLength = testStr.length() + 1;
    myfile.write( (const char*) &strLength, sizeof(strLength) );
    myfile.write( testStr.c_str(), strLength );
 
    myfile.close();
 
} // save
 
 
 
void Test::load(string fname)
{
    float testFloat = 0.0;
    string testStr = "";
    int strLength = 0;
 
    ifstream myfile;
    myfile.open ( fname, ios::in | ios::binary );
    myfile.read( (char*) &testFloat, sizeof(testFloat) );
 
    myfile.read( (char*) &strLength, sizeof(int) );
 
    char* buf = new char[strLength];
    myfile.read( buf, strLength );
    testStr = buf;
 
    myfile.close();
 
    cout << testFloat << endl;
    cout << strLength << endl;
    cout << testStr << endl;
 
} // load

Allocate & Free a 2D array (C++ style)

int **dynamicArray = 0;
 
//memory allocated for elements of rows.
dynamicArray = new int *[ROWS] ;
 
//memory allocated for  elements of each column.
for( int i = 0 ; i < ROWS ; i++ )
   dynamicArray[i] = new int[COLUMNS];
 
//free the allocated memory
for( int i = 0 ; i < ROWS ; i++ )
   delete [] dynamicArray[i] ;
delete [] dynamicArray ;

When to to use delete[] and when delete?

You delete [] when you newed an array type, and delete when you didn't. Examples:

typedef int int_array[10];
 
int* a = new int;
int* b = new int[10];
int* c = new int_array;
 
delete a;
delete[] b;
delete[] c; // this is a must! even if the new-line didn't use [].

Function call with argument pass by reference vs. pass by value

struct Object {
    int i;
};
 
void foo(Object* o) // 1
{
    o->i++;
    Logger::Access()->Log( QString("Hello from foo version #1: o.i=%0").arg(o->i) );
}
 
void foo(Object & o) // 2
{ 
    o.i++;
    Logger::Access()->Log( QString("Hello from foo version #2: o.i=%0").arg(o.i) );
}
 
void foo(Object const& o) // 3
{ 
    // object o cannot modified here! It is constant.
    Logger::Access()->Log( QString("Hello from foo version #3: o.i=%0").arg(o.i) );
}
 
void foo2(Object o) // 4
{ 
    o.i++;
    Logger::Access()->Log( QString("Hello from foo version #4: o.i=%0").arg(o.i) );
}
 
 
int main()
{   
    Object obj = { 10 };
    Object const obj_c = { 10 };
 
    Logger::Access()->Log( QString("obj.i = %0").arg(obj.i) );
    foo(&obj); // calls 1
    Logger::Access()->Log( QString("obj.i = %0\n").arg(obj.i) );
 
    Logger::Access()->Log( QString("obj.i = %0").arg(obj.i) );
    foo(obj); // calls 2
    Logger::Access()->Log( QString("obj.i = %0\n").arg(obj.i) );
 
    Logger::Access()->Log( QString("obj_c.i = %0").arg(obj_c.i) );
    foo(obj_c); // calls 3
    Logger::Access()->Log( QString("obj_c.i = %0\n").arg(obj_c.i) );
 
    Logger::Access()->Log( QString("obj.i = %0").arg(obj.i) );
    foo2(obj); // calls 4
    Logger::Access()->Log( QString("obj.i = %0\n").arg(obj.i) );

will produce the following output:

obj.i = 10
Hello from foo version #1: o.i=11
obj.i = 11

obj.i = 11
Hello from foo version #2: o.i=12
obj.i = 12

obj_c.i = 10
Hello from foo version #3: o.i=10
obj_c.i = 10

obj.i = 12
Hello from foo version #4: o.i=13
obj.i = 12

So we pass a reference to the object with foo version #1,#2, and #3. Foo version #3 cannot modify the object that is passed by the reference, since it is const.

Only for foo version #4 we pass the object by value (= a copy of it). Therefore we modify a copy of the object, not the object that 'lives' in the main() method.

Exporting a class to a A.DLL + linking against the corresponding A.lib

I always forget how this works… Here are my notes since I did it right now:

In the 1st A.vcxproj that generates a DLL specify a preprocessor symbol DO_EXPORT.

#ifdef DO_EXPORT
    #define EXPORT_OR_IMPORT __declspec(dllexport)
#else
    #define EXPORT_OR_IMPORT __declspec(dllimport)
#endif
 
class EXPORT_OR_IMPORT A
{
public:
    A();
    ~A();
    foo();
};

The pre-processor definition DO_EXPORT will make sure, your .DLL and .lib will be generated.

In the 2nd B.vcxproj that wants to use class A do NOT define the preprocessor symbol DO_EXPORT, but link against A.lib.

That's it!

References:

Append one std::vector vec2 to another std::vector vec1

vec1.insert( vec1.end(), vec2.begin(), vec2.end() );

Checking whether std::string str2 is a substring of std::string str1

See here:

string str1 ("There are two needles in this haystack.");
string str2 ("needle");
 
if (str1.find(str2) != string::npos)
   return true;
else
   return false;
 
public/c.txt · Last modified: 2013/03/14 10:41 (external edit) · []
Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki