Должен ли я вернуть gsl::span<const T> вместо const std:: vector<T>&
У меня есть класс с членом std:: vector
class demo {
public:
//...
const std::vector<int> & test() const {
return iv;
}
private:
std::vector<int> iv;
};
Я планирую изменить тип члена на другой массив, такой как тип контейнера, с достаточной функциональностью и меньшим объемом памяти (например, std:: эксперимент:: dynarray, std:: unique_ptr
class demo {
public:
//...
gsl::span<const int> test() const {
return iv;
}
private:
std::vector<int> iv;
};
Но это нарушает код, который работал с константным вектором
demo d;
std::cout << (d.test().begin() == d.test().begin()) << "\n";
std::cout << (d.test().end() == d.test().end()) << "\n";
for( auto it = d.test().begin(), end = d.test().end(); it != end; ++it )
std::cout << *it << "\n";
Это печатает 0 0 и затем терпит крах, потому что проверить это! Конечно, диапазон, основанный на цикле, работает, но этот цикл действителен и поэтому должен также работать как положено. Я ожидал, что все диапазоны из одного и того же диапазона одного и того же контейнера равны, так что итераторы любого из этих диапазонов сравнимы (контейнер, конечно, не изменен). Конечно, есть веская причина, почему это не так.
Поэтому мой вопрос заключается в том, каков наилучший способ вернуть такое представление элементам массива, таким как контейнер, тип которых не должен быть виден вызывающей стороне.
2 ответа
Ты используешь iterator
временный, так что ваш iterator
стать инвалидом сразу после воздействия.
Вы можете использовать следующее:
auto&& view = d.test();
for (auto it = view.begin(), end = view.end(); it != end; ++it) {
std::cout << *it << "\n";
}
Так что ответ НЕТ, потому что он нарушает код, который был действителен раньше.