How to Delete Pointers in Vector or Map in Single Line?

2 03 2009


If you have two or three STL containers which holds pointers in your class as members, then I’m sure that its destructor will be the worst readable one. For deallocating STL containers, we have to iterate through each container by for loop, then delete it. But is there any single line function call to delete all pointers in vector or map, just like chopping the top of a tray of eggs at once? ๐Ÿ˜‰

deletestlcontainers
Picture Courtesy – elitalice.com


You can use for_each() and functors to achieve this. Check out the code snippet.

1) How to delete Vector of pointers in single line

// Necessary headers.
#include "functional"
#include "vector"
#include "algorithm"

using namespace std;

// Functor for deleting pointers in vector.
template<class T>
struct DeleteVectorFntor
{
    // Overloaded () operator.
    // This will be called by for_each() function.
    bool operator()(T x) const
    {
        // Delete pointer.
        delete x;
        return true;
    }
};

// Test Function.
void TestVectorDeletion()
{
    // Add 10 string to vector.
    vector<CString*> StringVector;
    for( int Index = 0; Index < 10; ++Index )
    {
        StringVector.push_back( new CString("Hello"));
    }

    // Now delete the vector in a single  line.
    for_each( StringVector.begin(),
              StringVector.end(),
              DeleteVectorFntor<CString*>());
}

1) How to delete Map of pointers in single line

// Necessary headers.
#include "functional"
#include "map"
#include "algorithm"

using namespace std;

// Functor for deleting pointers in map.
template<class A, class B>
struct DeleteMapFntor
{
    // Overloaded () operator.
    // This will be called by for_each() function.
    bool operator()(pair<A,B> x) const
    {
        // Assuming the second item of map is to be
        // deleted. Change as you wish.
        delete x.second;
        return true;
    }
};

// Test function.
void TestMapDeletion()
{
    // Add 10 string to map.
    map<int,CString*> StringMap;
    for( int Idx = 0; Idx < 10; ++Idx )
    {
        StringMap[Idx] = new CString("Hello");
    }

    // Now delete the map in a single  line.
    for_each( StringMap.begin(),
              StringMap.end(),
              DeleteMapFntor<int,CString*>());
}


STL is really a powerful toolkit. Isn’t it?


Targeted Audience – Intermediate.





Accessing empty vector will always throw exception?

23 07 2008


Vectors are cool! if we access out of array, they will throw unhandled exception. I used to get a lot. ๐Ÿ™‚

But are you sure that you’re vector always throw exception if you access out of array?


Answer is NO. Well have a look at the code snippet. At first we access an empty vector which throws an exception. Then we insert some values and then clear the vector to make it empty. Then if we access the empty vector, it won’t throw exception! Have a look at it.

// This class is just to access the protected members
// of vector.
class IntVector : vector<int>
{
    friend void CheckVector();
};

void CheckVector()
{
    IntVector IntArray;

    try
    {
        // Try to access element which result in exception.
        int Value = IntArray[ 0 ];
    }
    catch( ... )
    {
        // It will reach here since we're trying
        // to access an empty vector.
    }

    // Now add one value and clear the vector.
    IntArray.push_back( 10 );
    IntArray.clear();

    try
    {
        // Now try to access element. You can access it
        // eventhough the vector is empty.
        int Value = IntArray[ 0 ];
    }
    catch( ... )
    {
        // It will not reach here.
    }

    // Check the size of memory allocation inside vector.
    int InternalSize = _msize( IntArray._First );
    int VectorSize = IntArray.size();

Well, the reason is optimization. While clearing the vector, for optimization it won’t removes the allocated memory. It just sets the size as 0. So if you access the data by using array operator, you’ll get old value.


The morel is always check the size of array before accessing it. Well the behavior is observed in Visual Studio 6.0. Different IDEs and platforms may show different behavior. Take care!


Targeted Audience – Intermediate.





How to manipulate bits easily?

6 06 2008


We usually use & operator for checking bits in an integer value. Is there any easy method to manipulate bits? You can use STL bitset container. But itโ€™s not a container like vector or list. So it does not have iterators.


The bitset should be initialized with the number of bits. See the sample code block below.

// Initialize bitset with number of bits required.
// Here its for holding an integer.
bitset<sizeof(int) * 8> IntegerBits = 12478;

// I wanna see the value in binary.
cout << "Binary of 12478 is :" << IntegerBits << endl;

// How many bits are present?
cout << "Number of bits:" << IntegerBits.size() << endl;

// Check whether 10th bit is set.
cout << "10th bit is:" << IntegerBits[10] << endl;

// Flip all bits and display.
IntegerBits.flip();
cout << "Flipped Binary of 12478 is :" << IntegerBits << endl;

Now getting and manipulating bits is just like a breeze. nah?


Targeted Audience – Beginners.





auto_ptr as pass by value to functions – you are going to face a crash.

12 05 2008


Memory leaks are our nightmare and auto_ptr’s are used for making our life easier which does automatic memory deletion. If a pointer is assigned to an auto_ptr, it will be deleted when the auto_ptr went out of scope. But use this automatic deletion carefully, especially while passing it as function arguments by value. You are going to face a crash!


The problem is “owership”. Every auto_ptr holds an ownership flag. when an auto_ptr is assigned to another auto_ptr, the ownership flag is transfered from first to second. And only the auto_ptr with ownership flag enabled, can delete the resource. This method is used to avoid multiple deletion of the same pointer kept by several auto_ptrs. There will be only one owner auto_ptr at a time.

Now when you pass the auto_ptr by value, actually, you are passing the owner ship to the stack variable of the called function. Now the stack parameter will become the owner of your pointer and when the function returns, the auto_ptr in stack will be destructed and since its the owner, it will delete your passed pointer. When you access you main auto_ptr, then you’ll probably get a crash!!! See the code snippet for an e.g.

// Function which receives auto_ptr as value.
void ToUpper( auto_ptr<CString> pString )
{
    // Shows the messageBox.
    pString->MakeUpper();
}

// The one and only Main.
void main()
{
    // An auto_ptr which holds a CString.
    auto_ptr<CString> pString(
        new CString(_T("Hello AutoPtr")));

    // Make the string upper case by
    // passing it as value.
    ToUpper( pString );

    // At this point, your CString is already
    // been deleted by the stack variable in function.

    // Now change the string to Lower and face the crash!!!
    pString->MakeLower();
}


You can make the situation safe by passing by reference. While doing so, only a reference is passed to the stack variable and hence the ownership remains in you main auto_ptr itself.


Targeted Audience – Intermediate.





Seek uniqueness? Use STL set.

8 05 2008


In several conditions weโ€™ve to worry about avoiding duplicate data. For instance, if you have a combo-box which contains browsed file paths as history, it will be nice to avoid multiple occurrence of same file path. In those cases you can make use of STL set to remove duplicate data.


Set is a template class like any other STL container. For adding new data to set, you’ve to call insert() and for iterating you can use iterators. See sample code snippet below.

#include "set"
#include "string"
using namespace std;
...

// Set which is used to hold FilePaths as strings.
set<string> FilePathSet;

// I am inserting the same path a number of times.
// But finally, while iterating you can see only one
// copy of the same data.
FilePathSet.insert("C:\Windows\System32");
FilePathSet.insert("C:\Windows\System32");
FilePathSet.insert("C:\Windows\System32");
FilePathSet.insert("C:\Windows\System32");

// Iterate through the set.
set<string>::iterator FilePathSetItr = FilePathSet.begin();
while( FilePathSetItr != FilePathSet.end())
{
   // The unique data. Use it.
   string UniqueFilePath = *FilePathSetItr;

   // Increment to next item in set.
   ++FilePathSetItr;
}


Targeted Audience – Beginners.