TL;DR: Does the __block
attribute on an std::vector
prevent RVO in Objective-C++?
In Modern C++, the canonical way to return a vector from a function is to just return it by value so that return value optimization can be used if possible. In Objective-C++, this appears to work the same way.
- (void)fetchPeople {
std::vector<Person> people = [self readPeopleFromDatabase];
}
- (std::vector<Person>)readPeopleFromDatabase {
std::vector<Person> people;
people.emplace_back(...);
people.emplace_back(...);
// No copy is made here.
return people;
}
However, if the __block
attribute is applied to the second vector, then it appears that a copy of the vector is being created when it returns. Here is a slightly contrived example:
- (std::vector<Person>)readPeopleFromDatabase {
// __block is needed to allow the vector to be modified.
__block std::vector<Person> people;
void (^bloc)() = ^ {
people.emplace_back(...);
people.emplace_back(...);
};
block();
#if 1
// This appears to require a copy.
return people;
#else
// This does not require a copy.
return std::move(people);
#endif
}
There are plenty of Stack Overflow questions that explicitly state that you don't need to use std::move
when returning a vector because that will prevent copy elision from taking place.
However, this Stack Overflow question states that there are, indeed, some times when you do need to explicitly use std::move
when copy elision is not possible.
Is the use of __block
in Objective-C++ one of those times when copy elision is not possible and std::move
should be used instead? My profiling appears to confirm that, but I'd love a more authoritative explanation.
(This is on Xcode 10 with C++17 support.)
Aucun commentaire:
Enregistrer un commentaire