472,995 Members | 1,661 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,995 software developers and data experts.

vector erase

I have a vector from which I want to erase elements between iterators i,j.
If i<j, everything works as expected, but if j>i, an insertion is actually
performed. Example:

vector<double> x(10);
vector<double>::iterator i=x.begin()+2, j=x.begin()+6;

x.erase(i,j); // i<j, ok, erases 4 elements.
x.erase(j,i); // j>i, no error, just inserts 4 elements.

This happens with g++ 4.0.2. Is this standard behavior? Why does it work
this way?
Jan 27 '06 #1
9 5134
"Amadeus W. M." <am*******@cablespeed.com> wrote in
news:pa****************************@cablespeed.com :
I have a vector from which I want to erase elements between iterators
i,j. If i<j, everything works as expected, but if j>i, an insertion is
actually performed. Example:

vector<double> x(10);
vector<double>::iterator i=x.begin()+2, j=x.begin()+6;

x.erase(i,j); // i<j, ok, erases 4 elements.
x.erase(j,i); // j>i, no error, just inserts 4 elements.

This happens with g++ 4.0.2. Is this standard behavior? Why does it
work this way?


No. It is Undefined Behaviour. When you pass two iterators to erase (and
many other functions taking two iterators), it is your responsibility to
ensure that the second iterator (j) is reachable from the first iterator
(i) only by invoking operator++ on it. Since you tried to pass them
backwards, erase() probably started by attempting to iterate from j to i,
and went flying off the end of the vector.
Jan 27 '06 #2
In article <pa****************************@cablespeed.com>,
"Amadeus W. M." <am*******@cablespeed.com> wrote:
I have a vector from which I want to erase elements between iterators i,j.
If i<j, everything works as expected, but if j>i, an insertion is actually
performed. Example:

vector<double> x(10);
vector<double>::iterator i=x.begin()+2, j=x.begin()+6;

x.erase(i,j); // i<j, ok, erases 4 elements.
x.erase(j,i); // j>i, no error, just inserts 4 elements.

This happens with g++ 4.0.2. Is this standard behavior? Why does it work
this way?


The second erase is undefined behavior, the implementation can do
whatever it wants, including insert elements. I'm curious though how it
can insert elements when it doesn't have access to the vector's
push_back member-function... Are you sure that's what it is doing?
Jan 27 '06 #3
Andre Kostur <nn******@kostur.net> wrote in
news:Xn*******************************@207.35.177. 135:
"Amadeus W. M." <am*******@cablespeed.com> wrote in
news:pa****************************@cablespeed.com :
I have a vector from which I want to erase elements between iterators
i,j. If i<j, everything works as expected, but if j>i, an insertion
is actually performed. Example:

vector<double> x(10);
vector<double>::iterator i=x.begin()+2, j=x.begin()+6;

x.erase(i,j); // i<j, ok, erases 4 elements.
x.erase(j,i); // j>i, no error, just inserts 4 elements.

This happens with g++ 4.0.2. Is this standard behavior? Why does it
work this way?


No. It is Undefined Behaviour. When you pass two iterators to erase
(and many other functions taking two iterators), it is your
responsibility to ensure that the second iterator (j) is reachable
from the first iterator (i) only by invoking operator++ on it. Since
you tried to pass them backwards, erase() probably started by
attempting to iterate from j to i, and went flying off the end of the
vector.


Or... it probably starting copying from j+1 onto i (and j+2 to i+1, etc)
until (again) it eventually walked off the end of the vector. Then by
happenstance it stopped before actually crashing your problem (or perhaps
a debug-mode version of the standard library that checked to make sure
that you don't iterate off the end of a container). In either case, it's
still Undefined Behaviour.
Jan 27 '06 #4
Andre Kostur wrote:
Or... it probably starting copying from j+1 onto i (and j+2 to i+1, etc)
until (again) it eventually walked off the end of the vector. Then by
happenstance it stopped before actually crashing your problem (or perhaps
a debug-mode version of the standard library that checked to make sure
that you don't iterate off the end of a container). In either case, it's
still Undefined Behaviour.


Implementation of erase(iterator::start, itertaor::end) first does a
copy from [iterator::end, vector::end()] in to vector starting at
iterator::start. So when iterator::end > iterator::start world is fine.
But when iterator::start > iterator::end then it would actuall copy
from iterator::start (which is greater than iterator::end till
vector::end() ) to vector::end() starting from iterator::end. Hence
instead of deleting it adds to the end first and then deletes from the
difference.

Below is one the implementation of vector::erase() which I thought
might be usefull in understanding the behaviour.

iterator __i(std::copy(__last, end(), __first));
std::_Destroy(__i, end());
this->_M_impl._M_finish = this->_M_impl._M_finish - \
(__last - __first);
return __first;

I am not sure as to why it was done this way but I think it's
developers responsibility to ensure that iterator::end >
iterator::start.

I did try out the example posted.
$ cat vec.cpp
#include <vector>
#include <iostream>

int main(int argc, char** argv) {
std::vector<int> x(10);
std::vector<int>::iterator i=x.begin()+2, j=x.begin()+6;

std::cout << "Size of vector " << x.size() << std::endl;
x.erase(i,j);
std::cout << "Size of vector " << x.size() << std::endl;
x.erase(j,i);
std::cout << "Size of vector " << x.size() << std::endl;
return 0;
}
$ ./a.out
Size of vector 10 [ Before deletion ]
Size of vector 6 [ After deletion ]
Size of vector 10 [ Adds 8 and then deletes 4 ]
$

Thank you,
Nitin Motgi (nmotgi)

Jan 27 '06 #5
Andre Kostur wrote:
Or... it probably starting copying from j+1 onto i (and j+2 to i+1, etc)
until (again) it eventually walked off the end of the vector. Then by
happenstance it stopped before actually crashing your problem (or perhaps
a debug-mode version of the standard library that checked to make sure
that you don't iterate off the end of a container). In either case, it's
still Undefined Behaviour.


Implementation of erase(iterator::start, itertaor::end) first does a
copy from [iterator::end, vector::end()] in to vector starting at
iterator::start. So when iterator::end > iterator::start world is fine.
But when iterator::start > iterator::end then it would actuall copy
from iterator::start (which is greater than iterator::end till
vector::end() ) to vector::end() starting from iterator::end. Hence
instead of deleting it adds to the end first and then deletes from the
difference.

Below is one the implementation of vector::erase() which I thought
might be usefull in understanding the behaviour.

iterator __i(std::copy(__last, end(), __first));
std::_Destroy(__i, end());
this->_M_impl._M_finish = this->_M_impl._M_finish - \
(__last - __first);
return __first;

I am not sure as to why it was done this way but I think it's
developers responsibility to ensure that iterator::end >
iterator::start.

I did try out the example posted.
$ cat vec.cpp
#include <vector>
#include <iostream>

int main(int argc, char** argv) {
std::vector<int> x(10);
std::vector<int>::iterator i=x.begin()+2, j=x.begin()+6;

std::cout << "Size of vector " << x.size() << std::endl;
x.erase(i,j);
std::cout << "Size of vector " << x.size() << std::endl;
x.erase(j,i);
std::cout << "Size of vector " << x.size() << std::endl;
return 0;
}
$ ./a.out
Size of vector 10 [ Before deletion ]
Size of vector 6 [ After deletion ]
Size of vector 10 [ Adds 8 and then deletes 4 ]
$

Thank you,
Nitin Motgi (nmotgi)

Jan 27 '06 #6
On Thu, 26 Jan 2006 20:54:38 -0500, Amadeus W. M. wrote:
I have a vector from which I want to erase elements between iterators i,j.
If i<j, everything works as expected, but if j>i, an insertion is actually
performed. Example:

vector<double> x(10);
vector<double>::iterator i=x.begin()+2, j=x.begin()+6;

x.erase(i,j); // i<j, ok, erases 4 elements.
x.erase(j,i); // j>i, no error, just inserts 4 elements.

This happens with g++ 4.0.2. Is this standard behavior? Why does it work
this way?

After looking at the code, it's no wonder that the result looks like an
insertion. In fact, I only tried on a vector with all elements the same.
On a random vector it won't look like an insertion.

I just wanted to know whether or not it was standard. It would have been
nice to throw an exception or something. Here is the code:

template<typename _Tp, typename _Alloc>
typename vector<_Tp, _Alloc>::iterator
vector<_Tp, _Alloc>::
erase(iterator __first, iterator __last)
{
iterator __i(std::copy(__last, end(), __first));
std::_Destroy(__i, end(), this->get_allocator());
this->_M_impl._M_finish = this->_M_impl._M_finish - (__last - __first);
return __first;
}

Very informative this open source thing!

Jan 27 '06 #7
"Amadeus W. M." <am*******@cablespeed.com> wrote in message
news:pa****************************@cablespeed.com ...
On Thu, 26 Jan 2006 20:54:38 -0500, Amadeus W. M. wrote:
I have a vector from which I want to erase elements between iterators
i,j.
If i<j, everything works as expected, but if j>i, an insertion is
actually
performed. Example:

vector<double> x(10);
vector<double>::iterator i=x.begin()+2, j=x.begin()+6;

x.erase(i,j); // i<j, ok, erases 4 elements.
x.erase(j,i); // j>i, no error, just inserts 4 elements.

This happens with g++ 4.0.2. Is this standard behavior? Why does it work
this way?

After looking at the code, it's no wonder that the result looks like an
insertion. In fact, I only tried on a vector with all elements the same.
On a random vector it won't look like an insertion.

I just wanted to know whether or not it was standard. It would have been
nice to throw an exception or something. Here is the code:

template<typename _Tp, typename _Alloc>
typename vector<_Tp, _Alloc>::iterator
vector<_Tp, _Alloc>::
erase(iterator __first, iterator __last)
{
iterator __i(std::copy(__last, end(), __first));
std::_Destroy(__i, end(), this->get_allocator());
this->_M_impl._M_finish = this->_M_impl._M_finish - (__last -
__first);
return __first;
}

Very informative this open source thing!


Yeah, one of the benefits of template libraries is that they pretty
much have to show all their code in publicly readable headers.
(Export templates haven't quite caught on yet, if they every will.)
So if by "open source" you mean code that you can see, then *all*
implementations of the Standard C++ library are pretty open, at
least the STL part.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jan 27 '06 #8
P.J. Plauger schrieb:
Very informative this open source thing!


Yeah, one of the benefits of template libraries is that they pretty
much have to show all their code in publicly readable headers.
(Export templates haven't quite caught on yet, if they every will.)
So if by "open source" you mean code that you can see, then *all*
implementations of the Standard C++ library are pretty open, at
least the STL part.


RMS would love this!
This shows exactly the difference between "Open Source" and "Free As in Speech" software.

/S
--
Stefan Naewe
naewe.s_AT_atlas_DOT_de
Jan 27 '06 #9
loquacious wrote:

Below is one the implementation of vector::erase() which I thought
might be usefull in understanding the behaviour.


To what end? The behavior is undefined, so whatever some implementation
does is simply what that implementation does. If you want to rely on
that behavior, so be it. But that's dangerous here, because conceptually
what's being done doesn't make sense, since the range to be erased isn't
a valid range.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jan 27 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Steve Hill | last post by:
Hi, suppose I have a vector allocated on the heap. Can I use a temporary (stack based vector) and swap to clear it, or is this unsafe. e.g. vector<int> *v; vector<int> tmp; v->swap(tmp); // is...
3
by: Jonathan | last post by:
Hey again everyone! I have another question for you guys. I am trying to erase a certain vector element based on what number the user selects. Here is what I did: case 'b' : { cout << "Please...
9
by: david wolf | last post by:
I want to delete all even numbers in a vector, I am not sure if there's any better way to do it. Following program is how I did it. Look at the part of code beginning from comments: //delete all...
5
by: Billy Patton | last post by:
I have a polygon loaded into a vector. I need to remove redundant points. Here is an example line segment that shows redundant points a---------b--------c--------d Both b and c are not...
14
by: cayblood | last post by:
I want to iterate through a vector and erase elements that meet a certain criteria. I know there is an algorithmic way of doing this, but first I would like to know how to do it with normal...
4
by: Christian Bruckhoff | last post by:
Hi. Is there a possibility to delete elements out of a vector? At the moment i do it by copying all needed elements to another vector. After clearing the old vector i copy them back element by...
3
by: =?iso-8859-1?q?Erik_Wikstr=F6m?= | last post by:
I have some code where there's this vector of pointers to objects and I need to delete and erase some of them, the problem is that to know which I need to iterate through the vector and I'm trying...
10
by: arnuld | last post by:
WANTED: /* C++ Primer - 4/e * * Exercise: 9.26 * STATEMENT * Using the following definition of ia, copy ia into a vector and into a list. Use the single iterator form of erase to...
3
by: chsalvia | last post by:
I have a question about the design of STL vector. One thing I wonder was why the STL designers chose to have the insert() and erase() functions take an iterator as the first argument, rather than...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
3
SueHopson
by: SueHopson | last post by:
Hi All, I'm trying to create a single code (run off a button that calls the Private Sub) for our parts list report that will allow the user to filter by either/both PartVendor and PartType. On...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.