Да, можно вернуть std::vector
из функции. И с этим мы можем, как сказано в ваших словах, «Инициализировать вектор с вектором». В C ++ мы можем использовать RVO, оптимизацию возвращаемого значения. Вы можете прочитать здесь о копировании elision и RVO. В основном это говорит о том, что у вас не будет проблем с копированием байтов при возврате контейнеров из функции по значению. Теперь это даже рекомендуемый способ сделать это.
Итак, вы можете (и должны) вернуть std::vector
из функции. Компилятор позаботится о том, чтобы это работало оптимизированным образом.
Но сначала посмотрите на приведенный ниже пример:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
std::vector<int> parseInts(std::string str) {
// Put the string into a stream
std::istringstream iss{ str };
// Return the vector of ints
return { std::istream_iterator<int>(iss), {} };
}
int main() {
// Test data
std::string test{ "1 2 3 4 5 6 7 8 9 10" };
// Get the vector with the ints
std::vector ints = parseInts(test);
// Show output
for (const int i : ints)
std::cout << i << "\n";
return 0;
}
У нас есть функция с именем parseInts
, состоящая всего из 2 строк. кода.
Сначала мы помещаем строку в поток istring. При этом можно будет извлечь int из нового потока, как в
std::istringstream iss{ str };
int i1, i2;
iss >> i1 >> i2;
Оператор экстрактора >> будет «извлекать» целочисленные значения, разделенные пробелом, из потока (строки).
Но, если мы посмотрим на это, мы увидим, что тогда нам нужно знать количество целых чисел в строке, а затем многократно писать «>>». Для повторного выполнения одного и того же количества элементов, например целых чисел, у нас есть итераторы в C ++. С помощью итераторов вы можете перебирать похожие элементы в контейнере. Если вы предполагаете, что строка является контейнером, вы, конечно, можете перебирать целые числа в ней. Есть доступные итераторы, которые делают это для нас.
В случае потока у нас есть std :: istream_iterator . Эта вещь будет перебирать все разделенные пробелами элементы определенного типа во входном потоке и возвращать значения.
Многие значения, которые возвращает этот итератор, лучше всего хранить в std::vector
, потому что это динамически растущий контейнер. Идеально для нас, потому что мы заранее не знаем количество целых чисел в потоке.
Если мы посмотрим на std::vector
, мы обнаружим, что у него есть так называемый конструктор диапазона. Пожалуйста, смотрите здесь: конструктор диапазона (число 5) .
С помощью конструктора диапазона мы определяем переменную типа std::vector
и инициализируем ее с помощью итератора «начало» и «конец» , Значения в этом диапазоне будут помещены в вектор.
Если мы определим переменную типа std::vector
в нашем примере, мы могли бы написать:
std::vector<int> intv{ std::istream_iterator<int>(iss), std::istream_iterator<int>() };
или
std::vector<int> intv( (std::istream_iterator<int>(iss)), std::istream_iterator<int>() );
Пожалуйста, не используйте скобки для первого аргумента. Это необходимо для защиты от самой неприятной проблемы разбора. Вы не хотите определять функцию, но переменную.
Но мы все равно не будем его использовать. Потому что с равномерной инициализацией и {} -initializer в качестве инициализатора по умолчанию. Мы можем использовать по умолчанию 2-й параметр. Теперь мы можем написать:
std::vector<int> intv(std::istream_iterator<int>(iss), {});
Итак, далее мы можем использовать CTAD, Вычет аргумента шаблона класса . По сути, компилятор знает из параметров конструктора, какой тип контейнера он будет создавать. Так что нет необходимости писать это.
Теперь:
std::vector intv(std::istream_iterator<int>(iss), {});
Это выглядит уже очень хорошо, и теперь вы можете вернуть переменную intv.
Но это еще не все. Компилятор знает тип функции и что она должна возвращать. Таким образом, вы можете использовать инициализированный скобками и возвращать это, и компилятор знает, что вы хотите вернуть std::vector<int>
Итак, последнее утверждение:
return { std::istream_iterator<int>(iss), {} };
Надеюсь, это поможет .
И извините за длинное описание для одной строки кода.