用向量初始化向量?

时间:2020-03-24 15:05:01

标签: c++ vector

我们能否通过返回类型vector的功能来初始化c ++中的vector。

#include <sstream>
#include <vector>
#include <iostream>
using namespace std;

vector<int> parseInts(string str) {
    // Complete this function
}

int main() {
    string str;
    cin >> str;
    vector<int> integers = parseInts(str); /** here is the problem **/
    for(int i = 0; i < integers.size(); i++) {
        cout << integers[i] << "\n";
    }

    return 0;
}

3 个答案:

答案 0 :(得分:0)

是的,可以从函数返回std::vector。这样一来,就像您所说的那样,“用向量初始化向量”。在C ++中,我们可以利用RVO,即返回值优化。您可以阅读here有关复制省略和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的函数,仅包含两行代码。

首先,我们将字符串放入istringstream中。这样,就有可能像

一样从新流中提取int。
std::istringstream iss{ str };
int i1, i2;
iss >> i1 >> i2;

提取器运算符>>将从流(字符串)中“提取”空格分隔的整数值。

但是,如果我们看一下,就会发现,我们需要知道字符串中整数的数量,然后重复写入“ >>”。为了重复处理相同数量的项(例如整数),我们在C ++中提供了迭代器。使用迭代器,您可以遍历容器中的相似元素。如果您假设字符串为容器,则当然可以遍历其中的整数。有可用的迭代器可以为我们完成此任务。

对于流,我们有std::istream_iterator。这个东西将遍历输入流中某种类型的所有以空格分隔的项目,并返回值。

此迭代器返回的许多值最好存储在std::vector中,因为它是一个动态增长的容器。对我们来说很理想,因为我们不预先知道流中的整数数量。

如果我们查看std::vector,就会发现它具有所谓的范围构造函数。请在此处查看:range constructor (number 5)

使用范围构造函数,我们定义了std::vector类型的变量,并使用“ begin”和“ end”迭代器对其进行了初始化。此范围内的值将被放入向量中。

如果在示例中定义类型为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为默认初始化器。我们可以使用默认的2nd参数。现在我们可以写:

std::vector<int> intv(std::istream_iterator<int>(iss), {});

因此,接下来,我们可以使用CTAD Class template argument deduction。基本上,编译器从构造函数中的参数知道它将构造容器的哪种数据类型。因此,无需编写它。

现在:

std::vector intv(std::istream_iterator<int>(iss), {});

这看起来已经非常不错了,您现在可以返回变量intv。

但是还有更多。编译器知道函数的类型以及应该返回什么。因此,您可以使用支撑的初始化程序并将其返回,并且编译器知道您要返回std::vector<int>

最后的声明是:

return { std::istream_iterator<int>(iss), {} };

我希望这会有所帮助。

对于一行代码的详细说明,我们深表歉意。

答案 1 :(得分:-3)

#include <sstream>
#include <vector>
#include <iostream>
using namespace std;

vector<int> parseInts(string str) {    //this line tells that function will return an integer vector
    vector <int> hello;
    int n,ele;
    cout<<"Enter An Integer:";
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>ele;
        hello.push_back(ele);
    }
    return hello;           //vector named hello returned to main function
}

int main() {
    string str;
    cin >> str;
    vector<int> integers = parseInts(str); /** here is the problem **/
    for(int i = 0; i < integers.size(); i++) {
        cout << integers[i] << "\n";
    }
    return 0;
}

希望这会有所帮助

答案 2 :(得分:-3)

#include <sstream>
#include <vector>
#include <iostream>
using namespace std;

vector<int> parseInts(string str) {
    vector <int> hello;
    int n,ele;
    stringstream geek(str);              // object from the class stringstream 
    geek>>n;               //converts to int
    for(int i=0;i<n;i++)
    {
        cin>>ele;
        hello.push_back(ele);
    }
    return hello;
}

int main() {
    string str;
    cin >> str;
    vector<int> integers = parseInts(str); /** here is the problem **/
    for(int i = 0; i < integers.size(); i++) {
        cout << integers[i] << "\n";
    }
    system("pause");
    return 0;
}