简体   繁体   中英

Does std::unique invalidate vector iterators?

For this code:

std::vector<int> v = {...};
std::sort(v.begin(), v.end());

// Does this work?
std::size_t unique_count = std::unique(v.begin(), v.end()) - v.cbegin();

In the last line, I think since std::unique just moves stuffs around inside the vector and does not insert anything into it, no iterators should be invalidated, and so the way I'm calculating unique_count should be correct. But I want to make sure that is the case. Is it?

std::unique is an algorithm. All stl algorithms operate on ranges, not containers.

Although the algorithm may swap element contents, the iterators to those elements remain unchanged.

This is a guarantee.

If it were not, then this could not work:

#include <algorithm>
#include <vector>
#include <iostream>
#include <array>

int main()
{

  auto unique_size = [](auto&& container)
  {
    std::sort(std::begin(container), std::end(container));
    return std::unique(std::begin(container), std::end(container)) - std::cbegin(container);
  };

  std::cout << unique_size(std::vector<int> {6,5,4,4,3,2,1}) << std::endl;
  std::cout << unique_size(std::array<int,7> {6,5,4,4,3,2,1}) << std::endl;
  int x[] = {6,5,4,4,3,2,1};
  std::cout << unique_size(x) << std::endl;

    // Does this work? yes.
}

mandated output:

6
6
6

std::unique return an iterator to one position past the last 'unique' element in the container.

auto last = std::unique(v.begin(), v.end());

Then the range [ last , v.end() ) contains whatever, you can't rely on v.cbegin() . Instead:

auto unique_count = std::distance(v.begin(), last);

will do the trick.

http://en.cppreference.com/w/cpp/algorithm/unique

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM