Reputation: 1007
If we use the range-based for loop with strings, is there any gain using
for (auto const & c : s)
over
for (auto c : s)
// c => char
// s => std::string
I'm asking this because chars which are just one byte in memory are not that expensive to copy, and this kept me curious last night.
I did some benchmarks on it!
RESULT:
// In Milliseconds
// 1000
// BY COPY: 7
// BY _REF: 5
// 10000
// BY COPY: 51
// BY _REF: 50
// 100000
// BY COPY: 503
// BY _REF: 501
// 1000000
// BY COPY: 5047
// BY _REF: 5101
// 10000000
// BY COPY: 52058
// BY _REF: 56160
CODE:
#include <chrono>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
bool by_copy(std::string const & s);
bool by_const_ref(std::string const & s);
int main() {
std::string const test {"0000000001"};
auto start {std::chrono::steady_clock::now()};
for (unsigned long long i {}; i < 10000000; ++i) {
bool b {by_copy(test)};
if (b) {}
}
auto end {std::chrono::steady_clock::now()};
auto duration {std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()};
cout << "BY COPY: " << duration << '\n';
start = std::chrono::steady_clock::now();
for (unsigned long long i {}; i < 10000000; ++i) {
bool b {by_const_ref(test)};
if (b) {}
}
end = std::chrono::steady_clock::now();
duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
cout << "BY _REF: " << duration << '\n';
return 0;
}
bool by_copy(std::string const & s) {
for (auto c : s) {
if (c == '1') {
return true;
}
}
return false;
}
bool by_const_ref(std::string const & s) {
for (auto const & c : s) {
if (c == '1') {
return true;
}
}
return false;
}
UPDATE
Out of curiosity, I also did benchmarks on by index, and it was way much more faster than the range-based for loops, why?
RESULTS
// 1000
// BY COPY: 7
// BY _REF: 5
// BYINDEX: 4
// 10000
// BY COPY: 59
// BY _REF: 58
// BYINDEX: 37
// 100000
// BY COPY: 526
// BY _REF: 495
// BYINDEX: 326
// 1000000
// BY COPY: 5751
// BY _REF: 5038
// BYINDEX: 3308
// 10000000
// BY COPY: 62202
// BY _REF: 63002
// BYINDEX: 38744
the by_index function:
bool by_index(std::string const & s) {
for (size_t i {}; i < s.size(); ++i) {
if (s[i] == '1') {
return true;
}
}
return false;
}
Upvotes: 0
Views: 308
Reputation: 238351
To clarify, I interpret your question such that you are iterating over the characters of a string - rather than iterating a container of strings.
No, there is no advantage. In fact, there is theoretically potential for the reference being slower due to the implied indirection. However, it is likely that both variations compile to exactly the same machine code because a decent optimizer will be able to avoid the indirections.
Upvotes: 1