C++ vector manipulation

hi

i have a vector to which i want to add elements at random places. (I only say random because the act of insertion is not serial or sequential , rather it is formulaic.)

I have a vector defined like so:
std::vector<int> i;
std::vector<int>::iterator  begin=i.begin();


When I add i want to say something like this:
i.insert(begin+offset,myvalue);


However, if i have an empty i to begin with, so the iterator begin is a bad pointer.

How can i store the correct begin position for an empty vector?

i guess i could check to see if the vector was empty, add the first element, get begin to point to the first element etc. But i think this approach is inelegant. Can I somehow do things in the approach mentioned above?
LuckyLucksAsked:
Who is Participating?
 
ambienceCommented:
In general, it is a bad idea to store stl iterators, unless there is a really good reason for that and you really know what you are doing. For a vector, you can just use the indexer or i.begin() whenever needed.

STL iterators (at least for VC) use internal mechanism like container proxies to invalidate iterators whenever a container mutates (such as when new items are added). This is extra baggage in debug mode with the benefit that you trap errors easily and write safe code. For all practical purposes, as a general DESIGN principle of STL, you should not consider an iterator to be valid after mutating the container.

The following code throws an exception, because the vector has mutated - invalidating the iterator - even though, logically, the iterator should still be able to insert at head

	
        std::vector<int> i;
	i.resize(10);
	
	std::vector<int>::iterator  begin = i.begin();
	i.resize(100); // comment this line and it works
	i.insert(begin, 10);

Open in new window

0
 
jkrCommented:
>>However, if i have an empty i to begin with, so the iterator begin is a bad pointer.

Not really. it is a 'pesudo iterator', such as 'vector::end()'. Even with an empty map, you can always use

i.insert(i.begin()+offset,myvalue);

Open in new window


You just can't use it as 'begin=i.begin();' if 'i' is empty and use it further.
0
 
sarabandeCommented:
you cannot add at position i if the vector has not already i elements.

so for an empty vector the statement

i.insert(i.begin()+offset,myvalue);

Open in new window

would throw an exception if offset is greater 0.

note, the iterator end() is a pseudo iterator only when the vector is empty and no internal array exists. in all other cases it points to a real address one slot behind the last element.

because of that you also could use pointers to a  c array when a function requires iterators:

std::string arr[4]  = { "ABC", "DEF", "GHI", "JKL" };
std::string * f = std::find(&arr[0], &arr[4], "XYZ");
if (f != &arr[4])
{
     // string found
      ... 

Open in new window


note, in the above sample code &arr[4] is an invalid pointer as it points to non-allocated memory. however, the address is not invalid but well defined.

Sara
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LuckyLucksAuthor Commented:
I am getting Debug Assertion failed

at

Expression ("this->_Has_container()",0)

in the vector.h file (see line _SCL_SECURE_VALIDATE....

_Myt& operator+=(difference_type _Off)
            {      // increment by integer
            _SCL_SECURE_VALIDATE(this->_Has_container());
            _SCL_SECURE_VALIDATE_RANGE(
                  _Myptr + _Off <= ((_Myvec *)(this->_Getmycont()))->_Mylast &&
                  _Myptr + _Off >= ((_Myvec *)(this->_Getmycont()))->_Myfirst);
            _Myptr += _Off;
            return (*this);
            }
0
 
jkrCommented:
Using which code? At which line of that?
0
 
sarabandeCommented:
the assertion is because you tried to access the vector beyond its current size. for example if the vector has two elements and you try to access the 3rd element. or if you want to insert with offset 10 but the vector has only 8 elements.

if you want to have a vector which automatically grows if you insert beyond its current size(creating 'empty' elements between), you need to do like

bool MyClass::insertWithGrow(std::vector<MyType> & v, const MyType & mt, int offset)
{
     if (offset < 0) return false;
     if (offset > (int)v.size())
     {
           v.resize(offset);   // grow the vector before inserting
     }
     v.insert(v.begin()+offset, mt);
     return true;
}

Open in new window


Sara
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.