Add buffer to hash table RetrieveData is a 3rd party API that takes 3 parameters: a buffer, number of bytes to retrieve, and actual bytes required for the buffer.


The buffer returned is a non-null terminated unicode string
99% of the time, the buffer is less than 256 bytes, but may be larger and needs to handle this scenario
RetrieveData(data) is guaranteed to return 
The reason for using std::map is the ID must later be retrieved based on a string




std:map&lt;std::wstring, unsigned int&gt; map_columns;
unsigned int id;
unsigned long pcbActual;
char* data;

do 
{
    RetrieveID(&amp;id);
    // find out how large buffer we need to retrieve data
    RetrieveData(NULL, 0, &amp;pcbActual);
    data = new char[pcbActual + 2];
    // actually retrieve data
    RetrieveData(data, pcbActual, &amp;pcbActual);
    data[pcbActual] = '\0';
    data[pcbActual + 1] = '\0';
    std::wstring str((wchar_t*)data);
    map_columns[str] = id;
} while (MoveNext());
Jerry Coffin has already pointed out that your current code leaks memory all over the place, which could certainly be slowing it down (since the heap allocator will have to go get more and more and more memory to feed the leaky code, instead of just reusing the same memory every time).



Consider using std::unordered_map&lt;std::wstring, unsigned int&gt;, as a hash lookup is likely to be O(1) and faster than the O(lg N) lookup associated with a std::map (which is basically the same thing as Java's TreeMap).



Move semantics are your friend. Use them to eliminate all the expensive reallocations and memcpys that are happening in your code. I count three memcpys: once inside RetrieveData, then again from data into str, then again from str into map_columns.



Minor nit: Declare your variables in the smallest, tightest scopes possible; this will aid the optimizer as well as helping the human reader understand the code.



Putting it all together, we get something like this:

std::unordered_map&lt;std::wstring, unsigned int&gt; map_columns;

do {
    unsigned int id;
    RetrieveID(&amp;id);
    unsigned long len;
    RetrieveData(nullptr, 0, &amp;len);
    assert(len % 2 == 0);  // len is measured in 2-byte units
    std::wstring data((len/2)+1);
    RetrieveData(data.data(), len, &amp;len);
    map_columns.emplace(std::move(data), id);
} while (MoveNext());


(You might need to cast data.data() to (void*) or (char*); I don't know. You might also want to see whether the third argument to RetrieveData can be nullptr; or, if not, maybe you should use a temporary variable and assert that the new value is exactly the same as the old value, since it would be Very Bad if that weren't true.)



Oh, and I strongly suspect that you're eventually going to run into problems where you're looking up a Unicode string in your map and you don't find it when you thought you would, because of Unicode normalization issues. So, be prepared for that, if you can.