C++ – Is list::size() really O(n)


Recently, I noticed some people mentioning that std::list::size() has a linear complexity.
According to some sources, this is in fact implementation dependent as the standard doesn't say what the complexity has to be.
The comment in this blog entry says:

Actually, it depends on which STL you
are using. Microsoft Visual Studio V6
implements size() as {return (_Size);
} whereas gcc (at least in versions
3.3.2 and 4.1.0) do it as { return std::distance(begin(), end()); } The
first has constant speed, the second
has o(N) speed

  1. So my guess is that for the VC++ crowd size() has constant complexity as Dinkumware
    probably won't have changed that fact since VC6. Am I right there?
  2. What does it look like currently in gcc? If it is really O(n), why did the
    developers choose to do so?

Best Solution

In C++11 it is required that for any standard container the .size() operation must be complete in "constant" complexity (O(1)). (Table 96 — Container requirements). Previously in C++03 .size() should have constant complexity, but is not required (see Is std::string size() a O(1) operation?).

The change in standard is introduced by n2923: Specifying the complexity of size() (Revision 1).

However, the implementation of .size() in libstdc++ still uses an O(N) algorithm in gcc up to 4.8:

  /**  Returns the number of elements in the %list.  */
  size() const _GLIBCXX_NOEXCEPT
  { return std::distance(begin(), end()); }

See also Why is std::list bigger on c++11? for detail why it is kept this way.

Update: std::list::size() is properly O(1) when using gcc 5.0 in C++11 mode (or above).

By the way, the .size() in libc++ is correctly O(1):

size_type size() const _NOEXCEPT     {return base::__sz();}


__compressed_pair<size_type, __node_allocator> __size_alloc_;

const size_type& __sz() const _NOEXCEPT
    {return __size_alloc_.first();}