|
don't delete elements from a map while iterating through it, you'll probably end up accessing pairs that are deleted.
Er zit een korstje op mijn aars.
|
|
|
|
|
When you delete an element, any iterators pointing at that element become invalid. So after calling MyMap.erase(MyIterator) you can't use MyIterator again (like in the ++ expression) unless you reset it first.
--Mike--
Ericahist | CP SearchBar v2.0.2 | Homepage | RightClick-Encrypt | 1ClickPicGrabber
There is a saying in statistics that a million monkeys pounding on typewriters would eventually create a work of Shakespeare. Thanks to the Internet, we now know that this is not true.
|
|
|
|
|
Just to add to the previous comments, the following
for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); )
{
MyMap.erase(MyIterator++);
} is correct.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
... and just one line more.
typedef map< char*, int > STRING2INT;
instead
typedef map STRING2INT; // it's never going to work
Miro
|
|
|
|
|
I didn't see the declaration of STRING2INT , as the original poster forgot to tick the "Do not treat <'s as HTML tags" checkbox
Now that you have revealed the definition of STRING2INT to the world, another subtler flaw comes to light. The type
map< char*, int > does not guarantee the behavior one would assume at first sight. Even worse, it can seem to work until less expected. The problem is that what's being used as a key are pointers to chars, and pointing to equivalent contents does not imply pointer equality. Consider:
typedef map< char*, int > STRING2INT;
STRING2INT m;
m["January"]=1;
cout<<m["January"]<<endl; No guarantee is made that the first pointer in #1 is the same as that in #2. Usually, this equality happens to work because the compiler is smart enough not to duplicate literals, but the following will fail for sure
m["January"]=1;
string str="January";
cout<<m[str.c_str()]<<endl; Of course, the simple solution is to define STRING2INT as a map< string, int > . Regards,
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Yes, char* is difficult to manipulate, but char* also is a pointer to
null terminated string - the basic C/C++ strings primitive type (well know "C" string).
A little modification of "The problem is that what's being used as a key are pointers to chars". No the key are pointers to null terminated strings.
Now let's see the code.
typedef map<string, int > STRING2INT; // Thank's Mike
m["January"]=1;
string str="January";
// cout<<m[str.c_str()]<<endl; /* You can not do that.
The compilers are not enough smart */
const char* key = str.c_str(); // init that's ok
cout<<m[ key ]<<endl; // now is correct
some more ....
m["January"]=1;
// Bytes -> 012345678901 the next (12) byte is '\0'
// ||||||||||||
char somearr[] ="MonthJanuary";
char* psomearr = &somearr[5]; // lets take the address of the fifth byte
char** ppkey = &psomearr; // let's try indirect
cout<<m[ psomearr ]<<endl; // ok
cout<<m[ (*ppkey) ]<<endl; // also ok
Of course, I agree with you the simple solution is to define STRING2INT as a map< string, int >.
Best regards,
Miro
|
|
|
|
|
miropl wrote:
const char* key = str.c_str(); // init that's ok
cout<<m[ key="" ]<<endl;="" now="" is="" correct<="" i="">
That shouldn't even compile if the type of m is map<char*,int> , since key is a const char* and not a char* (as referenced in the template).
In fact, on VS.NET 2k3 and GCC 3.2.3, the following code:
#include <map>
#include <iostream>
using namespace std;
typedef map<const char*,int> mymap_t;
int main(int argc, char* argv[]) {
mymap_t m;
m["January"]=1;
string str="January";
const char* key = str.c_str();
cout << m[key] << endl;
return 0;
}
Prints out 0 instead of 1 .
The reason why is the crux of what Joaquín was saying -- it doesn't matter what the char* is pointing to (whether it's a zero-terminated C string or a big buffer of random char crud), the key is treated as a simple char pointer, and thus takes on pointer comparison semantics when used in the map .
Here's a simpler example of how things can go wrong with char* :
#include <conio.h>
#include <map>
#include <iostream>
using namespace std;
typedef map<char*,int> mymap_t;
int _tmain(int argc, _TCHAR* argv[]) {
mymap_t m;
m["January"]=1;
char *str = strdup( "January" );
cout << m[str] << endl;
free(str);
return 0;
}
- Mike
|
|
|
|
|
By the way, if you want to make the map empty then just call clear()
|
|
|
|
|
Yu Zhiquan wrote: for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); MyIterator++)
{
MyMap.erase(MyIterator);
}
the moment u call MyMap.erase(MyIterator), the size is reduced and begin() has changed. so in your for loop, MyIterator++ is directing u to the "3rd" element.
u should use while loop to delete by check the size, not begin till end.
from,
-= aLbert =-
|
|
|
|
|
I developed an activeX and I managed to add it to a richeditctrl but the problem is that the activeX doesn't handel its messages that I alread add a handel for them so my question first any suggested solutions and is this a general problem arises with activeX or not
thanks in advance
|
|
|
|
|
Using both together, I cant overcome some problems with locales.
I am getting a C2668 in \vc98\include\xlocnum : 'sprintf' ambiguous call to overloaded function
When I dont include the regex, all compiles just fine. I just dont get it. HEEEEEEEEEEEEEEEEELP. please.
Finally moved to Brazil
|
|
|
|
|
I use VC6 and check "Add common controls manifest" in the WTL wizard.
But then I compile my apps they have classic windows style.
Manifest doesn't work!
Then I recompile samples from this site it doesn't work. Why? Bug in the wizard? In VC? I
don't understand. Please help me!
|
|
|
|
|
What OS are you running?
Steve S
|
|
|
|
|
|
this was happening to me long time ago when I had an old SDK that didn't define RT_MANIFEST in any header file. So that's your primal suspect; try getting the latest platform SDK
|
|
|
|
|
Hi All,
I am writing an ATL/COM extension for a mapping application. All is fine except I am struggling to get field validation on Edit boxes to work.
I open up a Modal ATL dialog and the user does there thing, but when it comes to the OnOk button event my code bombs when I try to get the text from the edit boxes
<br />
BSTR field1;<br />
BSTR field2;<br />
<br />
this->GetDlgItemText(IDC_WIZEDIT1, field1); <br />
<br />
this->GetDlgItemText(IDC_WIZEDIT2, field2);<br />
EndDialog(wID);<br />
<br />
The error when I try the above is:
Application Error-
The instruction at "0x0f074b68" referenced memory at "0x0f074b68". The memory could not be "read"
Which is not a very helpful message.
In short, is there a an easy way to validate resources on an ATL dialog?
thanks for your time in advance
cheers
Bryce
|
|
|
|
|
At the risk of stating the obvious, have you tried setting the BSTR variables to NULL first?
It's eminently possible that it contains a garbage value. This causes the code to attempt to SysFreeString it first, and it's likely that is tripping the error. The eip looks about right for being somewhere in the system, rather than in "your" code.
Steve S
|
|
|
|
|
Hi Steve,
Thanks for your help! You hit the nail on the head with your reply... exactly the problem.
Will remember that one from now on.
Another quick question if you can be bothered answering:
Is it the programmers responsability to do the SysFreeString if they have called SysAllocString, or will be taken care of by the compiler? (Am relatively new to the ATL/COM system, and have had the luxury of the automatic garbage collection in java)
Is there a general rule for COM objects for when they should be ->Release() or ->Detach(). It seems that if I call CoCreateInstance, then I need to call ->Release() otherwise if I have a smartpointer where I define it in a local scope, then I can only call ->Detach() or it is destroyed when scope is lost.
Thanks once again
cheers
Bryce
|
|
|
|
|
Hi Steve,
Thanks for your help! You hit the nail on the head with your reply... exactly the problem.
Will remember that one from now on.
Another quick question if you can be bothered answering:
Is it the programmers responsability to do the SysFreeString if they have called SysAllocString, or will be taken care of by the compiler? (Am relatively new to the ATL/COM system, and have had the luxury of the automatic garbage collection in java)
Is there a general rule for COM objects for when they should be ->Release() or ->Detach(). It seems that if I call CoCreateInstance, then I need to call ->Release() otherwise if I have a smartpointer where I define it in a local scope, then I can only call ->Detach() or it is destroyed when scope is lost.
Thanks once again
cheers
Bryce
|
|
|
|
|
Depends. If you're writing a COM client (ie you're using objects and passing BSTR values in), the general rule is that if you allocate, you must free. There's a _bstr_t (and a CComBSTR) type that is like a smart-pointer for BSTRs but it's not perfect.
If you have a smart-pointer to an interface, then it will call Release on destruct.
Non-smart pointers don't, so you should. You wouldn't call Detach unless you needed a raw interface for some reason.
Steve S
|
|
|
|
|
I have CheckBox in TreeControl (from WTL). Please let me know how can i receive Event notification from checkbox when it is selected/unselected. I tried LButtonDOwm and OnClick but it does not work.
For LButtonDOwn i used
NOTIFY_HANDLER(IID_TC, WM_LBUTTONDOWN, OnLButtonDown) but control does not come to this.
For click i am unable to detect on which item was clicked.
NOTIFY_HANDLER(IID_TC, NM_CLICK, OnClick)
Thanks
Shiv
|
|
|
|
|
Place the following code into OnClick:
#define MSG_CHECKSTATECHANGE (WM_USER + 1001)
DWORD dwpos = GetMessagePos();
TVHITTESTINFO ht;
ht.pt.x = GET_X_LPARAM(dwpos);
ht.pt.y = GET_Y_LPARAM(dwpos);
::MapWindowPoints(HWND_DESKTOP, pnmh->hwndFrom, &ht.pt, 1);
::TreeView_HitTest(lpnm->hwndFrom, &ht);
// If click on checkbox then post user defined message
if(TVHT_ONITEMSTATEICON & ht.flags)
{
PostMessage(MSG_CHECKSTATECHANGE, 0, (LPARAM)ht.hItem);
}
You can also send the MSG_CHECKSTATECHANGE message from TVN_KEYDOWN notify handler when SPACE key is pressed.
|
|
|
|
|
I made an activeX control with ATL.
The control has one property.
In the .html file, the source code looks like below:
<object
classid="clsid:c3043399-79bd-4bca-ab35-7dc1a206af4a"
codebase="http: www.chinagrovetech.com="" i3d="" i3dformproj.cab#version="1,0,0,0"
width=800" height="600
">
<param name="movie" value="test.i3d" />
The control is a little like the flash player which can play .swf files.
Now I want the control to player .i3d files, and the file format is customed.
If the value of "movie" is an absolute path, everything is OK, but when it is a relative path, my control is not able to know the file's location.
Please help me !
stanley
|
|
|
|
|
If I know I'll be dealing with millions of objects, and assigning them to vectors, is there an algorithm I can use to determine what size I should initially set the vector to, in order to avoid (as much as possible) the vector from constantly growing (which it is constantly doing as more and more objects are "pushed" into it)?
For example, if the vector is going to grow from 200K to 400K, and then from 400K to 800K, and from 800K to 1.6 Million (and so forth), I'd like to set the vector to 2 million right from the very start, just to avoid the system from having to use up time constantly allocating more space, then copying from the old over to the new (etc.), and simply cut to the chase.
It's an algorithm I looking for that would let me enter the variables and have it give me a good estimate of what size I sould make the vector at the beginning.
Thanks for any insight.
William
Fortes in fide et opere!
|
|
|
|
|
The solution depends on the type of object. What object is it?
Kuphryn
|
|
|
|