7

If a container is likely to contain a large number of items, from a performance perspective, should one write

for (auto p = std::begin(container); p != std::end(container); ++p) {...}

or should one access the container's end outside the loop

const auto& theEnd = std::end(container);
for (auto p = std::begin(container); p != theEnd; ++p) {...}

I just wonder if std::end is O(1) for containers like sets and lists as well as vectors.

RJFalconer
  • 10,890
  • 5
  • 51
  • 66
  • 1
    the optimization probably depends on the compiler, you can also initialize the end element in the initialization part of the for loop – Marco A. Aug 07 '14 at 13:09
  • 1
    Note that `C` can count here too, and depending on your loop body, end() might change. – PlasmaHH Aug 07 '14 at 13:11
  • 2
    @MarcoA. Compilers won't be able to change the asymptotic complexity, they only do micro-optimizations. – Paul Manta Aug 07 '14 at 13:11
  • @PaulManta: Thats not quite correct. If a compiler can prove your inner loop to always result in the same value, it can reduce `N*N` to `N`, which is however a rare case to happen. Yet alone understanding datastructures... – PlasmaHH Aug 07 '14 at 13:12
  • @PaulManta I was not referring to that though. I was talking (from a performance perspective) of the comparison in the condition part – Marco A. Aug 07 '14 at 13:12
  • almost certainly, the code generated from these two alternatives will be identical for most compilers and most containers. – Walter Aug 07 '14 at 13:12
  • I don't know if `std::end` itself is required to be constant time, but the biggest offender, `std::list::end`, is indeed constant, so I would assume yes. – Paul Manta Aug 07 '14 at 13:13
  • 1
    `.begin()` and `.end()` have guaranteed constant complexity, see [container.requirements.general] – dyp Aug 07 '14 at 13:14
  • @PlasmaHH True. I meant that it won't change the asymptotic complexity unless it is a trivial case. – Paul Manta Aug 07 '14 at 13:14
  • Related/duplicate: http://stackoverflow.com/q/83640/420683 – dyp Aug 07 '14 at 13:15
  • Probably duplicate of: http://stackoverflow.com/q/9768447/420683 – dyp Aug 07 '14 at 13:16
  • I'm tempted to -1 for lack of research effort. – dyp Aug 07 '14 at 13:17
  • Constant complexity or not, the constant time it adds can be non negligible for simple loops. And since uses return by value, `auto const&` is likely less effective than simply `auto`. – James Kanze Aug 07 '14 at 14:04
  • There was a talk given by Chandler Carruth where he stated that using `.end()` in the loop conditional is a nightmare for the optimiser (in Clang), so regardless I would hoist it out anyway. – Simple Aug 07 '14 at 15:20

2 Answers2

5

Yes, the complexity for end() is constant for all containers. The table "Container requirements" in C++ Standard 23.2.1 says so:

a.end() constant

Wojtek Surowka
  • 20,535
  • 4
  • 44
  • 51
4

According to container requirements described in Table 96 of the C++ Standard function end() has constant complexity.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335