Does std::unique invalidate iterators ever?

A

Alan Woodland

Is this well defined behaviour?

#include <vector>
#include <string>
#include <algorithm>

int main() {
std::vector<std::string> content;

content.push_back("foo");
content.push_back("bar");
content.push_back("foo");

// make sure the content is unique, discard any duplicates
std::sort(content.begin(), content.end());
content.erase(std::unique(content.begin(), content.end()),
content.end());

return 0;
}

My concern is that the order of evaluation of the arguments passed to
erase() is unspecified, and therefore that unique could invalidate the
iterator returned by end(). If I've understood things correctly then
unique can't invalidate any iterators and so the example code is well
defined?

Thanks,
Alan
 
V

Victor Bazarov

Alan said:
Is this well defined behaviour?

#include <vector>
#include <string>
#include <algorithm>

int main() {
std::vector<std::string> content;

content.push_back("foo");
content.push_back("bar");
content.push_back("foo");

// make sure the content is unique, discard any duplicates
std::sort(content.begin(), content.end());
content.erase(std::unique(content.begin(), content.end()),
content.end());

return 0;
}

My concern is that the order of evaluation of the arguments passed to
erase() is unspecified, and therefore that unique could invalidate the
iterator returned by end(). If I've understood things correctly then
unique can't invalidate any iterators and so the example code is well
defined?

Usually in the Standard any iterator invalidations are explicitly
stated. Since for 'unique' nothing is mentioned, I'd say that iterators
are not invalidated. The elements can get different values, yet
whatever points to them will still be OK to dereference, increment,
decrement, or pass to algorithms expecting an iterator. With the vector
the 'end' stays "one past last" except when it reallocates or elements
are erased. Since no elements are erased during 'unique', you should be OK.

V
 
J

James Kanze

Is this well defined behaviour?
#include <vector>
#include <string>
#include <algorithm>
int main() {
std::vector<std::string> content;

// make sure the content is unique, discard any duplicates
std::sort(content.begin(), content.end());
content.erase(std::unique(content.begin(), content.end()),
content.end());
return 0;
}
My concern is that the order of evaluation of the arguments
passed to erase() is unspecified, and therefore that unique
could invalidate the iterator returned by end(). If I've
understood things correctly then unique can't invalidate any
iterators and so the example code is well defined?

Iterators are never invalidated unless the topology of the
container is modified. Algorithms never modify the topology of
the container, since they don't even know that the container
exists.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top