C++ 的新手并试图围绕 initializer_list 进行思考。
我正在创建一个 Matrix 类,它可以有效地存储 double 值的二维数组。我没有在结构层面上了解该项目。好吧,我们创建了一个 Matrix 类,它本质上存储了一个二维数组数据。但是它需要能够存储任意大小的数组,所以它必须使用动态分配的数组。但是 std::array 是不允许的。
我不知道如何访问 i_list 中的项目。如果他们像这样传入
Matrix a = {{1, 2}, {3, 4}};
然后根据我看到的文档,我在构造函数中与该信息交互的唯一选择是 list.begin() ,它指向 {1, 2} 和 list.end() ,它指向{3,4}
std::vector 和 std::array 被项目描述禁止,非动态数组显然不能为大小取变量。
那么我如何让它能够读取任何大小的矩阵,以及如何从我的 i_list 中获取这些值并将它们存储到非动态的东西中?
我在想像
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 等库类。您必须使用动态分配的数组在内部实现 Matrix 类
最佳答案
initializer_list
是非常便宜的 [references to] 临时对象的容器。
您可以像处理数组一样遍历它们。此外,它们还有一个 size()
成员,因此您可以查询它们的尺寸。
这是将“2d”initializer_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 }
}
Printing out the contents of the list is pretty simple, but what if I want to save them non-dynamically? I'm making a class constructor, and I want to have access to that data.
好的,所以要求类中的存储是非动态的(即固定大小)。
我将做一些假设:
- 假设目标类是一个 3x3 矩阵
- initializer_list 中任何未指定的项目都应假定为零。
- 传入超过 3 行或 3 列是逻辑错误,应该引发异常
这是(许多)方法之一:
#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;
}
but I wanted a dynamically-sized 2-d array...
哦,那继续吧...
#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;
}
关于c++ - 如何从(嵌套的)std::initializer_list 确定大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38292224/