当前位置: 首页 > 知识库问答 >
问题:

如何从(嵌套的)std::initializer\u列表中确定大小?

冀望
2023-03-14

刚接触C语言的我,正试图了解initializer\u list。

我正在制作一个Matrix类,它有效地存储了一个双值的二维数组。我没有在结构层面上得到这个项目。就像好吧,我们制作了一个Matrix类,它本质上存储了一个2D数据数组。但是它需要能够存储任何大小的数组,所以它必须使用动态分配的数组。但是std::array是不允许的。

我不知道如何访问i_list中的项目。如果它们像

Matrix a = {{1, 2}, {3, 4}};

然后根据我看到的文档,我与构造函数中的信息交互的唯一选项是list。begin()指向{1,2}和列表。end()指向{3,4}

d::向量和std::array被项目描述禁止,非动态数组显然不能接受变量的大小。

那么,如何使其能够读取任何大小的矩阵,以及如何从I\U列表中获取这些值并将其存储到非动态的内容中呢?

我想象的是

Matrix::Matrix(const initializer_list & list) {
    double * mat[/*somehow find out size without dynamic allocation*/];
    for (double* i : mat) {
        *i = list[i]; //not how i_list works apparently
    }
}

项目描述说明:您不能在此项目中使用库类,如std::array、std::vector、std::list等。必须使用动态分配的数组在内部实现矩阵类

共有2个答案

蒲寂离
2023-03-14

也许,您正在寻找这样的东西:

struct Matrix {
  Matrix(std::initializer_list<std::initializer_list<double>> m) {
    int max=0;
    for (auto l: m)
      if (m.size()>max)
        max= m.size();
    std::cout << "your matriz seems to be: " 
              << m.size() << ' ' << max << std::endl;
  }
};
李俊雅
2023-03-14

initializer_lists是[引用]临时对象的非常便宜的容器。

您可以像遍历数组一样遍历它们。此外,它们还有一个size()成员,因此您可以查询它们的大小。

下面是一个将“2d”initializer\u list传递给函数(很容易成为构造函数)的示例:

#include <initializer_list>
#include <iostream>


using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;

void info(list_of_list_of_doubles lld)
{
    std::cout << "{\n";
    for (auto& ld : lld) {
        std::cout << "  {";
        auto sep = " ";
        for (auto& d : ld) {
            std::cout << sep << d;
            sep = ", ";
        }
        std::cout << " }\n";
    }

    std::cout << "}\n";
}

int main()
{
    info({
        { 1,2,3 },
        { 4.0, 5.0, 6.0 }
    });
}

预期输出:

{
  { 1, 2, 3 }
  { 4, 5, 6 }
}

打印出列表的内容非常简单,但是如果我想非动态地保存它们呢?我正在创建一个类构造函数,我想访问该数据。

好的,所以要求类中的存储是非动态的(即固定大小)。

我要做一些假设:

  1. 假设目标类是3x3矩阵

以下是一种(多种)方法:

#include <initializer_list>
#include <iostream>
#include <stdexcept>
#include <algorithm>


using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;

struct matrix
{
    matrix(list_of_list_of_doubles lld)
    : _storage {}
    {
        if (lld.size() > 3)
            throw std::invalid_argument("too many rows");
        auto row_idx = std::size_t { 0 };
        for (auto& row : lld) {
            if (row.size() > 3)
                throw std::invalid_argument("too many columns");
            std::copy(std::begin(row), std::end(row), std::begin(_storage[row_idx]));
            ++row_idx;
        }
    }

    double _storage[3][3];
};

std::ostream& operator<<(std::ostream& os, const matrix& m)
{
    std::cout << "{\n";
    for (auto& ld : m._storage) {
        std::cout << "  {";
        auto sep = " ";
        for (auto& d : ld) {
            std::cout << sep << d;
            sep = ", ";
        }
        std::cout << " }\n";
    }

    return std::cout << "}";
}

int main()
{
    matrix m({
        { 1,2,3 },
        { 4.1, 5.2, 6.3 },
        { 2.01, 4.5 }  // ,0
    });
    std::cout << m << std::endl;

}

但是我想要一个动态大小的二维阵列...

哦,那就继续吧。。。

#include <initializer_list>
#include <iostream>
#include <algorithm>
#include <numeric>


using list_of_doubles = std::initializer_list<double>;
using list_of_list_of_doubles = std::initializer_list<list_of_doubles>;

std::size_t total_extent(const list_of_list_of_doubles& lld)
{
    return std::accumulate(std::begin(lld), std::end(lld), std::size_t(0),
                           [](auto tot, auto& container) {
                               return tot + container.size();
                           });

}

struct matrix
{
    using value_storage = std::unique_ptr<double[]>;
    using index_storage = std::unique_ptr<std::size_t>;

    matrix(list_of_list_of_doubles lld)
    : _total_extent { total_extent(lld) }
    , _rows { lld.size() }
    , _indecies { new std::size_t[_rows] }
    , _storage { new double [_total_extent] }
    {
        auto istorage = _storage.get();
        auto iindex = _indecies.get();
        for (auto& row : lld) {
            *iindex++ = istorage - _storage.get();
            istorage = std::copy(std::begin(row), std::end(row), istorage);
        }
    }

    std::size_t rows() const {
        return _rows;
    }

    const double* column(std::size_t row) const {
        return std::addressof(_storage[_indecies[row]]);
    }

    std::size_t column_size(std::size_t row) const {
        return row == _rows - 1
        ? _total_extent - _indecies[row]
        : _indecies[row + 1] - _indecies[row];
    }

    std::size_t _total_extent, _rows;
    std::unique_ptr<std::size_t[]> _indecies;
    std::unique_ptr<double[]> _storage;
};

std::ostream& operator<<(std::ostream& os, const matrix& m)
{
    std::cout << "{\n";
    for (std::size_t row = 0 ; row < m.rows() ; ++row) {
        std::cout << "  {";
        auto sep = " ";
        for (std::size_t col = 0 ; col < m.column_size(row) ; ++col) {
            std::cout << sep << m.column(row)[col];
            sep = ", ";
        }
        std::cout << " }\n";
    }

    return std::cout << "}";
}

int main()
{
    matrix m({
        { 1,2,3 },
        { 4.1, 5.2, 6.3 },
        { 2.01, 4.5 }  // ,0
    });
    std::cout << m << std::endl;

}
 类似资料:
  • 在下面的代码中,我展示了类似联合的类S,它包含两个不相关的结构B和C。我展示了如何实例化非POD std::字符串并再次删除它,然后将S切换到S::CC 并设置num int。 然而,我的目标是在std::initializer\u列表中使用S。我不知道初始化h的格式应该是什么。如果我想用这些S::BB,S::CC,S::BB初始化h,参数应该是什么? 我的编译器是VS2015。 编辑:这篇文章的

  • 我试图用C(11/14)实现fortran的重塑功能,并设计了一个函数。此函数接受两个std::initializer\u列表。第一个initializer\u列表给出了我用来初始化多维数组的初始值。第二个initializer\u列表给出了数组每个维度的大小。我写了一份这样的草稿 这个实现需要给定的非类型模板参数int D,但我想要不带D的东西,比如重塑({1,2,3,4,5,6},{2,3})

  • 如果我有一个简单的结构 那我就可以了 现在,我希望在初始化点时有相同的行为,点成为类,但x和y变为私有并使用访问器等。 我的第一次尝试是 哪种工作但将编译时错误更改为运行时错误。现在的问题是:我如何使此类的行为与简单结构相同,即当初始化列表太大时导致编译时错误? 环顾四周,我发现 static_assertinitializer_list::size() 为什么size不是std::initial

  • GCC的实现销毁从返回完整表达式末尾的函数返回的数组。这是正确的吗? 该程序中的两个测试用例都显示了在可以使用该值之前执行的析构函数: 我认为这个计划应该奏效。但基本标准有点复杂。 return语句初始化返回值对象,就像它被声明一样 这将初始化给定系列初始化器中的一个临时初始化器列表及其底层数组存储,然后从第一个初始化器列表初始化另一个初始化器列表。阵列的生存期是多少?“数组的生存期与初始化器列表

  • 我是Java8新手,需要重写一段旧代码来实现一个新的alghoritm。任务是过滤每个列表具有最大速度的对象。列表嵌套在地图中:道路的根地图,其中包含道路段的地图,每个道路段的地图包含对象列表,每个对象以时间间隔降低测量的速度。我需要找到每个列表的所有最大速度。 我发现以下链接看起来像我的问题,但我不能适应他们,我不确定我的尝试解决我的问题正确。 如何使用Java8流和过滤器过滤嵌套循环? Jav

  • 问题内容: 我有以下格式的字典: 演示代码: 我无法获得嵌套字典在内存中的存储方式,因为size如果是136个字节,size是80个字节,而且size是520个字节。 另外,当我对类型从到的变量数据进行类型转换时,字符串变量的大小为。 演示代码: 可以解释一下为什么吗? 问题答案: 字典和列表存储 引用 (类似于Python中的其他所有标准容器)。不遵循引用,它给你的C结构的内存占用 唯一 。引用