Re: Problems with std::map.insert() and std::map.find()
(2b|!2b)==? schrieb:
Additionally, once the first item has been stored, no additional items
can be stored - its driving me nuts, and I cant work outt why this is
happening. I have included both my classes (i.e class template and key
class here - hopefully, someone can spot what is causing things to go
awry). To summarize the problem - every - i.e. find() and insert() work
as expected, UNTIL the first item is inserted into the map - which seems
to suggest that somehow, the Keys are considered non-unique???
How does find() and insert() both work "as expected" while you haven't
inserted any items?
The code follows below:
PointerMap.h
=============
#pragma once
This is non-standard. Unless you want to use this exclusively on
compilers that support it (i.e. Visual C++), you should use a regular
include guard here.
#include <string>
#include <map>
#include <stdexcept>
template<class T1, class T2>
class PointerMap
{
public:
typedef typename std::map<T1, T2*>::reference reference;
typedef typename std::map<T1, T2*>::const_reference const_reference;
typedef typename std::map<T1, T2*>::const_iterator const_iterator;
typedef typename std::map<T1, T2*>::iterator iterator;
PointerMap()
{
}
~PointerMap()
{
clear();
}
iterator begin() { return m_map.begin(); }
iterator end() { return m_map.end(); }
const_iterator begin() const { return m_map.begin(); }
const_iterator end() const { return m_map.end(); }
iterator find(T1 key) { return m_map.find(key) ; }
const_iterator find(T1 key) const { return m_map.find(key) ; }
iterator erase(iterator where)
{
if(where != m_map.end() && *where)
{
T*& ptr = *where;
delete ptr;
ptr = 0;
}
return m_map.erase(where);
}
iterator erase(iterator begin, iterator end)
{
while(begin != end)
{
T2*& ptr = begin->second ;
if ( ptr != 0)
{
You don't need to test a pointer for NULL before deleting it. deleting
null pointers is well defined. Same above in the other erase function.
delete ptr ;
ptr = 0;
}
begin++;
}
return m_map.erase(begin, end);
}
void clear() { erase(begin(), end()); }
bool empty() const { return m_map.empty(); }
size_t size() const { return m_map.size(); }
void insert(T1 key, T2* val)
{
m_map.insert(std::pair<T1, T2*>(key, val));
}
T2* operator[] (const T1 idx) const
{
if (idx > m_map.size())
throw std::logic_error("Array bounds exceeded");
Why? m_map is not an array, it is a map. You can have a key, that is
larger than the size(). To test if a key is in the map, use find() and
check if it returns end().
else
return m_map[idx] ;
This shouldn't compile. You cannot use op[] on a const map!
}
T2*& operator[] (const T1 idx)
{
if (idx > m_map.size())
throw std::logic_error("Array bounds exceeded");
Same as above.
else
{
T2*& ptr = m_map[idx] ;
if (ptr)
{
delete ptr ;
ptr = 0 ;
}
Why, WHY, *Why* do you delete the pointer when you want to get it?
return m_map[idx] ;
Using the returned pointer is undefined behaviour because it is null.
}
}
private:
PointerMap(const PointerMap& source);
PointerMap& operator=(const PointerMap& source);
std::map<T1, T2*> m_map;
};
RepositoryKey.h
================
class RepositoryKey
{
public:
RepositoryKey(const unsigned char xch, const long ic, const
std::string& syb, const long fq = 0):
m_xch(xch), m_ic(ic), m_syb(syb), m_fq(fq)
{
}
RepositoryKey(const RepositoryKey& key):
m_xch(key.m_xch), m_syb(key.m_syb), m_ic(key.m_ic), m_fq(key.m_fq)
{
}
~RepositoryKey()
{
}
Non needed.
RepositoryKey& operator=(const RepositoryKey& key)
{
if (this != &key)
{
m_xch = key.m_xch;
m_syb = key.m_syb;
m_ic = key.m_ic ;
m_fq = key.m_fq ;
}
return *this;
}
Better to use the swap idiom here.
bool operator==(const RepositoryKey& key) const
{
return ( (m_xch == key.m_xch) && (m_syb == key.m_syb) &&
(m_ic == key.m_ic) && ((long)m_fq == (long)key.m_fq) );
}
bool operator < (const RepositoryKey& key) const
{
return ( (m_xch < key.m_xch) && (m_ic < key.m_ic) && ((long)m_fq
< (long)key.m_fq)
&& (_stricmp(m_syb.c_str(), key.m_syb.c_str()) < 0));
}
This is not a valid op< for sorting.
For comparing two keys, it goes like this:
{
if (key1 < other.key1)
return true;
else if (other.key1 < key1)
return false;
else
return key2 < other.key2;
}
unsigned char Id() const { return m_xch; }
long Ic() const { return m_ic; }
std::string Symbol() const { return m_syb; }
long Freq() const { return m_fq ; }
private:
unsigned char m_xch ;
long m_ic ;
std::string m_syb ;
long m_fq;
};
You should also provide some code that shows how you use these classes.
--
Thomas