Consider:
#include <string>
#include <string_view>
using namespace std;
string sv2s_1(string_view sv)
{
return string(sv.data(), sv.size());
}
string sv2s_2(string_view sv)
{
return string(sv.begin(), sv.end());
}
In sv2s_1
, string
needs to allocate the internal buffer at most once.
In sv2s_2
, string
doesn't know how large the internal buffer should be, so it must push back the characters one by one, and may reallocate and copy the internal buffer many times.
Provided that first
and last
are random access iterators, string(first, last)
can use last - first
to fast get the size of its internal buffer, so the performance is equal to string(ptr, size)
.
Question: If first
and last
are random access iterators,
Does the C++ standard guarantee string(first, last)
is equivalent to string(ptr, size)
in terms of performance?
I don't see such a requirement in the standard. The standard says that X(i, j)
constructs a sequence container equal to the range [i, j)
and that the complexity of the expression is sequence dependent.
Looking into a particular implementation, libstdc++
precomputes the range size for forward, bidirectional and random access iterators:
template<typename InIterator>
void basic_string<CharT, Traits, Alloc>::
_M_construct(InIterator beg, InIterator end, std::forward_iterator_tag) {
// ...
size_type dnew = static_cast<size_type>(std::distance(beg, end));
// ...
}
Note that std::bidirectional_iterator_tag
and std::random_access_iterator_tag
are derived from std::forward_iterator_tag
, and can be implicitly converted into it, so this _M_construct
overload is called for forward, bidirectional and random access iterators (and contiguous iterators in C++20).