首页 > 解决方案 > 将 carray 转换为 istream 的 initializer_list

问题描述

我需要从流中读取数组元素,并且我有std::initializer_list<double>作为构造函数。我找不到与此相关的任何内容。carray是否可以从输入流中读取元素?我必须在Vector我定义的类中使用变量: double* datasize_t rows_

我的代码如下;

构造函数

Vector::Vector(std::initializer_list<double> il) : data(nullptr){`

    rows_ = l.size();
    data = new double[rows_];
    std::copy(il.begin(), il.end(), data); 
}

istream 的朋友功能

std::istream& operator >>(std::istream &inputStream, Vector& m) {

    
    double *buff = new double[m.rows_];
    
    for (size_t i=0; i !=m.rows_; ++i)
        is >> buff[i];
    
    // buff (array) --> initializer_list as "init_list"
    m = Vector(init_list);
    delete []buff;
    return inputStream; 
}

标签: c++arraysinitializer-lististream

解决方案


这个类std::initializer_list<T>是一个相当特殊的野兽。T它本质上以某种可以迭代的形式公开了位于内部堆栈上的一系列值。创建这样一个实体的唯一方法是实际上将值直接放在std::initializer_list<T>. 没有办法std::initializer_list<T>用可变数量的元素创建一个。

我的建议是为您的Vector类配备一个带有迭代器的构造函数,例如:

class Vector
{   
    std::unique_ptr<double[]> buff = 0;
    int                       size = 0;
    int                       capacity = 0;
public:
    template <typename InIt>
    Vector(InIt begin, InIt end) {
        for (auto it = begin; it != end; ++it) {
            if (size == capacity) {
                capacity = std::max(16, 2 * capacity);
                std::unique_ptr<double[]> tmp(new double[capacity]);
                std::copy(buff.get(), buff.get() + size, tmp.get());
                buff = std::move(tmp);
            }   
            buff[size++] = *it;
        }   
    }   
    // ...
};  

与 的舞蹈capacity是为了避免在序列很大的情况下操作的复杂性:一次增加一个元素(或任何固定数字n)的数组将具有二次复杂性。将阵列增加一个常数因子的方法会导致线性复杂度。理论上,您可以确定序列 ( std::distance(begin, end)) 的长度,但输入迭代器可能会消耗序列。

一旦该构造函数就位,您就可以使用如下流迭代器读取输入:

    Vector(std::istream& in)
        : Vector(std::istream_iterator<double>(std::cin),
                 std::istream_iterator<double>()) {
    }

推荐阅读