The Stupidest Miskates I Have Made
Here is a list of the stupidest mistakes I have made so far. So, from time to time, I can look at them and laugh at myself. 😂
title += "So Far..."
NOTE: all codes are mistakes!
How to convert a char
to an int
in C++
char c = '1';
int a = int(c);
assert( a == 1 ); // NO!
How to give a pointer a new
content in C++
int * ptr = nullptr;
void foo( int* ptr ){
ptr = new int(1);
}
assert( *ptr == 1 ); // NO!
How to grow a vector and iterate it at the same time in C++
// generate all products of 2^a \times 3^b
vector<int> v = {1};
int p = 2, q = 3, t = 30;
auto pitr = v.begin();
auto qitr = v.begin();
while( t -- ){
int x = *pitr*p, y = *qitr*q;
v.push_back( min( x,y ) );
if( x < y ){
++ pitr;
}else if ( x > y ) {
++ qitr;
}else{
++ pitr;
++ qitr;
}
}
assert( v[3] == 4 && v[7] == 12 ); // No!
How to use rval-reference in C++ to avoid copying
struct BitArray{
uint32_t* ptr; // stores bits
BitArray( size_t N ){ ptr = new uint31_t[N]; }
BitArray & operator=(BitArray && rhs){ // rval-ref
ptr = rhs.ptr; // move the ownership of the allocated chunk to avoid copy
rhs.ptr = NULL; // so it does not deallocate the chunk
}
};
/* can you spot a memory leak? */
Solutions
If you have not figure it out:
-
C++, like C, the conversion is a change of interpretation of the same segment of memory. C is using ASCII, a 7-bits table. Every char has 8-bits, or 2-hexadecimal. For example, char ‘0’ is
30
in hex, which means three 16s. So it is 48 inint
. The right way to convert a char from digit to int is by the difference ofc - '0'
. -
This is one is a funny one. The function passes a copy of the pointer, a pointer points to whatever memory address the original pointer pointing to. The memory allocated within the function is pointed by this temporary pointer. After the function ends, this temporary pointer is destroyed, and the original pointer left unchanged. Worst of all, the allocated memory can never be deallocated, classic memory leak. The right way is to pass the pointer by reference:
foo( int*& ptr )
; -
When vector is growing, it will reallocate new memory, probably at some other place, once its size reaches any power of 2. This will make iterators, essentially a pointer, invalid. The right way is either to
reserve
enough space at the beginning,v.reserve(50)
. If the size is unknown at the beginning, probably the best practice is to use indices. Note that, a similar issue also occurs when one delete elements while traversing a binary tree. I think C++11 provides a way to solve it aserase
method returns an iterator. The BGL, boost graph library, also makes vertex (edge) iterators invalid if the graph topology changes. Same idea. -
Before assign the
ptr
to the new address, we need to deallocate its memory.if (allocated) delete [] ptr; ptr = rhs.ptr;
I thank my mentor for pointing this mistake out.