Reputation: 9292
In a member function, I want to return a newly created vector of strings.
Which version is the most efficient from a memory allocation & constructor calling point of view? theString(i)
returns a const std::string &
std::vector<std::string> result(depth());
for(int i=0;i<depth;i++) {
result[i] = theString(i);
}
or
std::vector<std::string> result;
result.reserve(depth());
for(int i=0;i<depth;i++) {
result.emplace_back(theString(i));
}
To me it seems that:
reserve
(or is there an even more efficient solution?)
Upvotes: 0
Views: 633
Reputation: 299890
It's impossible to give a generic answer: depending on your compiler, the Standard Library implementation than you are using, the target CPU and the surrounding source code, the emitted code may vary. Furthermore, whether one solution or the other is faster may also be affected by cache effects or thread-switching effects caused by different scheduling.
So, unfortunately, there is no generic answer: measure with your setup.
That being said, let me offer two other candidates; candidate 3:
// The simplest code is always easier to read:
std::vector<std::string> result;
for (size_t i = 0; i < depth; ++i) { result.emplace_back(theString(i)); }
I would be surprised if it were much worse than your candidate 2. It relies on vector
's amortized constant emplace_back
and the fact that moving strings is cheap (compared to copying).
And candidate 4:
// If no copy is necessary, then no copy is cheaper:
std::vector<std::string_view> result; // or another "StringRef" alternative
for (size_t i = 0; i < depth; ++i) { result.emplace_back(theString(i)); }
The latter relying on string_view
: a non-owning reference to a string which is a very simply thing to implement (basically, a pair size_t
and char const*
) but is only viable if the referenced string is guaranteed to outlive the last use of the string_view
.
Upvotes: 2