基于结构中的向量大小初始化数组 [c++]

Initialization of array based on vector size in structure [c++]

本文关键字:初始化 数组 c++ 向量 于结构 结构      更新时间:2023-10-16

我正在尝试创建一个程序,将区域拆分为子集(此处为 8),每个子集包含 8 个值(对应于预定义的向量)。我定义了一个结构来存储这些值(以及向量):

struct Storage {
  static const int num_spatial_subset = 8;
  static const std::vector< std::vector<double> > vectors = 
    { {0,0,0}, 
      {0,1,0}, 
      {0,0,1}, 
      {1,1,0}, 
      {1,0,1}, 
      {0,1,1}, 
      {1,0,0}, 
      {1,1,1} };
  double storage[num_spatial_subset][vectors.size()];
};

但是,我在"向量"初始化时遇到编译错误:

 error: field initializer is not constant
       {1,1,1} };
               ^
 error: in-class initialization of static data member ‘const std::vector<std::vector<double> > Storage::vectors’ of non-literal type
 error: non-constant in-class initialization invalid for static member ‘Storage::vectors’
 error: (an out of class initialization is required)
 error: ‘Storage::vectors’ cannot be initialized by a non-constant expression when being declared
 error: array bound is not an integer constant before ‘]’ token
   double storage[num_spatial_subset][vectors.size()];

对于所有存储对象,向量都是相同的(这就是为什么我将它们定义为静态常量)。

我知道我可以用向量替换我的存储变量并在 Storage 的构造函数中调整它的大小,但这将涉及将第一个向量的大小调整为 8,并循环将所有内部向量的大小也调整为 8。由于我可能必须创建数千个这样的对象,因此我认为这不是执行此操作的最佳方法。

我真的不明白为什么编译器抱怨,因为向量是在编译时定义的(以及向量的数量)。

谢谢。

vector上调用size永远不会返回常量,因为它不符合常量C++规则。编译器不需要知道size()做什么,并且就其所知,它返回自程序开始执行以来的时间。如果您知道该值是常量,则可以定义一个保存该值的常量。但是编译器不需要具备为您执行此操作的知识。

即使编译器确实以某种方式知道该值是恒定的,它也会通过允许您编写这样的代码来伤害您。当下一个版本的库或编译器或其他编译器不知道时会发生什么?

错误:(需要类外初始化)

所以就做

struct Storage {
  static const int num_spatial_subset = 8;
  static const std::vector< std::vector<double> > vectors;
  double storage[num_spatial_subset][3];
};
const std::vector< std::vector<double> > Storage::vectors = 
    { {0,0,0}, 
      {0,1,0}, 
      {0,0,1}, 
      {1,1,0}, 
      {1,0,1}, 
      {0,1,1}, 
      {1,0,0}, 
      {1,1,1} };

作为替代方法,您可以使用initializer_list

struct Storage {
  static const int num_spatial_subset = 8;
  static constexpr std::initializer_list<std::initializer_list<double>> vectors{ {0,0,0}, 
      {0,1,0}, 
      {0,0,1}, 
      {1,1,0}, 
      {1,0,1}, 
      {0,1,1}, 
      {1,0,0}, 
      {1,1,1} };
  double storage[num_spatial_subset][vectors.size()];
};

演示

由于看起来vectors不打算在运行时调整大小,因此我放弃了vector并使用静态 2D 数组。

编辑:

简单的解决方案是从类中删除vectors,以便在需要大小之前可以完全定义它。

const double vectors[][3] =
{
    { 0, 0, 0 },
    { 0, 1, 0 },
    { 0, 0, 1 },
    { 1, 1, 0 },
    { 1, 0, 1 },
    { 0, 1, 1 },
    { 1, 0, 0 },
    { 1, 1, 1 }
    // add more here and storage will resize
};

我们无法从数组中获取数组中的行数,因此我们需要做一些工作来获取 Storage::storage 的大小。我们无法获取行,但是我们可以在编译时获取整个数组的大小(当前示例中为 sizeof(vectors) 或 8*3 *sizeof(double) = 192)和数组中行的大小(sizeof(vectors[0])或 3 *sizeof(double) 或 24)。将总大小除以行大小将得到行数 (192/24 = 8)。

struct Storage
{
    static const int num_spatial_subset = 8;
    // can't get the number of rows, but we can get the total size and divide 
    // it by the size of a row. 
    double storage[num_spatial_subset][sizeof(vectors) / sizeof(vectors[0])];
};

如果向量必须包含在Storage中,我们需要抽象以便在需要之前定义vectors的大小:

struct BaseStorage
{
    static const double vectors[][3];
};
const double BaseStorage::vectors[][3] =
{
    { 0, 0, 0 },
    { 0, 1, 0 },
    { 0, 0, 1 },
    { 1, 1, 0 },
    { 1, 0, 1 },
    { 0, 1, 1 },
    { 1, 0, 0 },
    { 1, 1, 1 }
    // add more here and storage will resize
};
struct Storage: public BaseStorage
{
    static const int num_spatial_subset = 8;
    double storage[num_spatial_subset][sizeof(vectors) / sizeof(vectors[0])];
};