Solved

C++ vector manipulation

Posted on 2014-01-23
6
656 Views
Last Modified: 2014-01-31
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?
0
Comment
Question by:LuckyLucks
6 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 39805188
>>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
 
LVL 33

Assisted Solution

by:sarabande
sarabande earned 250 total points
ID: 39805866
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
 

Author Comment

by:LuckyLucks
ID: 39822136
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
Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

 
LVL 86

Expert Comment

by:jkr
ID: 39822209
Using which code? At which line of that?
0
 
LVL 33

Expert Comment

by:sarabande
ID: 39823379
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
 
LVL 22

Accepted Solution

by:
ambience earned 250 total points
ID: 39823382
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

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question