В моем коде у меня есть что-то вроде этого:
vector<SuperHeavyObject> objects; // objects in this vector are extremely slow to copy!
for (auto &objectGroup : objectGroups) {
vector<SuperHeavyObject> objectsInThisGroup;
for (size_t index : objectGroup) {
objectsInThisGroup.push_back(objects[index]); // slow as copying is needed!
}
doSomething(objectsInThisGroup.begin(), objectsInThisGroup.end());
}
То, что я действительно хочу, это что-то вроде этого:
vector<SuperHeavyObject> objects; // objects in this vector are extremely slow to copy!
for (auto &objectGroup : objectGroups) {
vector<SuperHeavyObject*> objectsInThisGroup; // pointers!
for (size_t index : objectGroup) {
objectsInThisGroup.push_back(&objects[index]); // not slow anymore
}
doSomething(magicIterator(objectsInThisGroup.begin()),
magicIterator(objectsInThisGroup.end()));
}
doSomething
разрешено копировать объекты, поэтому проблем с областью видимости нет. внутри doSomething
это единственное место, где я хотел бы, чтобы происходило копирование, потому что эти объекты на самом деле очень медленно копируются (я профилировал, и это дроссельная точка).
В то же время я не хочу менять подпись doSomething
принимать итераторы разыменования SuperHeavyObject*
потому что это потребует много изменений; разыменование SuperHeavyObject
было бы идеально, так как это произошло бы только в одном месте (где происходит копирование).
Мой вопрос Я мог бы написать такой же итератор, но мне кажется, что я заново изобретаю колесо. Есть ли в C ++ (11) возможности для этого? У меня также есть Boost, если кто-то знает что-нибудь подобное.
Похоже, законный вариант использования для std::reference_wrapper
1:
vector<SuperHeavyObject> objects;
for (auto &objectGroup : objectGroups) {
vector<std::reference_wrapper<SuperHeavyObject>> objectsInThisGroup;
for (size_t index : objectGroup) {
// fast, we are only storing reference-like objects
objectsInThisGroup.push_back(objects[index]);
}
doSomething(objectsInThisGroup.begin(), objectsInThisGroup.end());
}
Спасибо @ matteo-italia за ваш полезный ответ! Я использовал его некоторое время, и решил присмотреться к итераторам Boost, и обнаружил, что у них есть indirect_iterator
что также является хорошим способом сделать то, что я хочу.
«irect_iterator адаптирует итератор, применяя дополнительную разыменование внутри оператора * () »
http://www.boost.org/doc/libs/1_59_0/libs/iterator/doc/indirect_iterator.html