Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Clarification for std::vector and std::map

Reply
Thread Tools

Clarification for std::vector and std::map

 
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      07-30-2003
On Wed, 30 Jul 2003 18:13:48 -0400, "Victor Bazarov"
<(E-Mail Removed)> wrote:

>"Sir_Ciph3r" <(E-Mail Removed)> wrote...
>> Can someone explain what is happening in the following code?

>
>Undefined behaviour.
>
>> #include <iostream>
>> #include <vector>
>> #include <map>
>>
>> using namespace std;
>>
>> int main()
>> {
>> vector<int> v;
>> map<char*,int*> m;
>>
>> v.push_back(99);
>> m["TEST"]=&v[0];

>
>You're saving a pointer to an object that may vanish into thin
>air at any point and the map won't know about it. That's called
>"asking for trouble".


I was just wondering if

map<char*, int> m;

m["TEST"] = 4;
m["TEST"] = 6;

is guaranteed to work, knowing that "TEST" is a pointer to a c-style
string. To me, it seems that a compiler is allowed to have two
different "TEST" strings and to map the values to the pointer address,
no?


Jonathan

 
Reply With Quote
 
 
 
 
Sir_Ciph3r
Guest
Posts: n/a
 
      07-30-2003
Can someone explain what is happening in the following code?

#include <iostream>
#include <vector>
#include <map>

using namespace std;

int main()
{
vector<int> v;
map<char*,int*> m;

v.push_back(99);
m["TEST"]=&v[0];

cout<<"Vec size: "<<v.size()<<" : "<<v[0]<<endl;

v.erase(&v[0]);

cout<<"Map: "<<*m["TEST"]<<endl;

cout<<"Vec size: "<<v.size()<<endl;

return 0;
}

I don't understand why I am getting "99" from this line of code

cout<<"Map: "<<*m["TEST"]<<endl;

I erased the vector element and the map only contained the address to
that vector element...yet I am still getting the value I pushed_back.
What is happening behind the scenes? Is this code safe?

Any help would be appreciated


 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      07-30-2003
"Sir_Ciph3r" <(E-Mail Removed)> wrote...
> Can someone explain what is happening in the following code?


Undefined behaviour.

> #include <iostream>
> #include <vector>
> #include <map>
>
> using namespace std;
>
> int main()
> {
> vector<int> v;
> map<char*,int*> m;
>
> v.push_back(99);
> m["TEST"]=&v[0];


You're saving a pointer to an object that may vanish into thin
air at any point and the map won't know about it. That's called
"asking for trouble".

> cout<<"Vec size: "<<v.size()<<" : "<<v[0]<<endl;
>
> v.erase(&v[0]);


There is no 'erase' member that takes a pointer to int. If your
implementation _happens_ to have vector::iterator the same as
a pointer to the contained type, it doesn't mean it will work
on any other computers/compilers/platforms. You have to pass
an iterator to 'erase'.

>
> cout<<"Map: "<<*m["TEST"]<<endl;


After the 'erase' (which probably worked by some weird chance)
you're trying to dereference a pointer that doesn't exist any
longer. The behaviour is undefined. You get your 99, but you
could as well get flying nasal demons.

>
> cout<<"Vec size: "<<v.size()<<endl;
>
> return 0;
> }
>
> I don't understand why I am getting "99" from this line of code
>
> cout<<"Map: "<<*m["TEST"]<<endl;
>
> I erased the vector element and the map only contained the address to
> that vector element...yet I am still getting the value I pushed_back.
> What is happening behind the scenes?


Impossible to say. Your code causes undefined behaviour.

> Is this code safe?


Absolutely not.

Victor


 
Reply With Quote
 
ES Kim
Guest
Posts: n/a
 
      07-30-2003
"Sir_Ciph3r" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Can someone explain what is happening in the following code?
>
> #include <iostream>
> #include <vector>
> #include <map>
>
> using namespace std;
>
> int main()
> {
> vector<int> v;
> map<char*,int*> m;
>
> v.push_back(99);
> m["TEST"]=&v[0];
>
> cout<<"Vec size: "<<v.size()<<" : "<<v[0]<<endl;
>
> v.erase(&v[0]);
>
> cout<<"Map: "<<*m["TEST"]<<endl;
>
> cout<<"Vec size: "<<v.size()<<endl;
>
> return 0;
> }
>
> I don't understand why I am getting "99" from this line of code
>
> cout<<"Map: "<<*m["TEST"]<<endl;
>
> I erased the vector element and the map only contained the address to
> that vector element...yet I am still getting the value I pushed_back.
> What is happening behind the scenes? Is this code safe?
>
> Any help would be appreciated
>
>


A container of raw pointers is usually not a good idea.
Use string and iterator instead of char* and int*.

int main()
{
vector<int> v;
map<string, vector<int>::iterator> m;

v.push_back(99);
m["TEST"]=v.begin();

cout<<"Vec size: "<<v.size()<<" : "<<v[0]<<endl;
cout<<"Map: "<<*m["TEST"]<<endl;

v.erase(v.begin());

// cout<<"Map: "<<*m["TEST"]<<endl;
// v.erase() invalidates m["TEST"]

cout<<"Vec size: "<<v.size()<<endl;

return 0;
}

--
ES Kim



 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      07-30-2003


Sir_Ciph3r wrote:

> I erased the vector element and the map only contained the address to
> that vector element...yet I am still getting the value I pushed_back.
> What is happening behind the scenes? Is this code safe?



You did all kinds of undefined behavior. Iterators and pointers into
vectors are invalidated as soon as you do any kind of operation on the
vector that make cause it to resize memory. Erase() certainly could have
done that. What probably happened with that the vector saw that you were
erasing the last element, so it just backed its valid end pointer by
one, and decreased the size so that the element you are pointing to will
be overwritten the next time.

What are you trying to accomplish?




Brian Rodenborn
 
Reply With Quote
 
Sir_Ciph3r
Guest
Posts: n/a
 
      07-31-2003
On Wed, 30 Jul 2003 18:13:48 -0400, "Victor Bazarov"
<(E-Mail Removed)> wrote:

Thanks for the help guys, I am slowing learning.

With this advice ->

>
>There is no 'erase' member that takes a pointer to int. If your
>implementation _happens_ to have vector::iterator the same as
>a pointer to the contained type, it doesn't mean it will work
>on any other computers/compilers/platforms. You have to pass
>an iterator to 'erase'.
>



Would this be a safe way to erase an element from a vector?

std::vector<CWindowKeeperWindow*>::iterator IVec;

// for(UINT i=0;i<uiSize;i++)
for(IVec=m_vecInstalledTimers.begin();
IVec!=m_vecInstalledTimers.end()
if((*IVec)->get_window_id()==hTreeItem)
{
//
m_vecInstalledTimers.erase(&m_vecInstalledTimers[i]);
IVec=m_vecInstalledTimers.erase(IVec);

#ifdef __CWINDOWKEEPER_DEBUG__
ConPrintf(_T("OnDeleteWindow() - erased timer
element\n"));
#endif
}
else
++IVec;
}
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
clarification needed for ecj and gcj Yao Java 1 06-19-2006 06:38 AM
Clarification on VLANS native and management madmax Cisco 6 03-14-2006 06:42 AM
Need clarification on asp_wp.exe,aspnet_wp.exe and aspnet_isapi.dll prem ASP .Net 1 11-03-2004 05:32 AM
Need some clarification and/or help with java NIO sockets HDSkiFreak Java 2 05-11-2004 01:48 PM
auto_ptr clarification and josuttis book lallous C++ 1 02-15-2004 10:25 AM



Advertisments