【问题标题】:Determine array size in constructor initializer在构造函数初始化程序中确定数组大小
【发布时间】:2009-04-15 14:08:43
【问题描述】:

在下面的代码中,我希望在调用 Class 构造函数时将数组定义为大小为 x 的数组。我该怎么做?

class Class
{
public:
  int array[];
  Class(int x) : ??? { }
}

【问题讨论】:

  • 如果您打算经常使用 C++,我强烈建议您熟悉标准模板库。它使处理数据集合更加更容易。
  • 顺便说一句,向量使得在事先不知道大小的情况下使用数组变得相对容易。无需事先知道尺寸;您可以使用 push_back 在(摊销的)O(1) 时间内将元素附加到向量的末尾。
  • 使用向量会带来新的问题,因为我试图向量化的类保护了“新”运算符。但这不是我问的,所以没关系。
  • @zaratustra:为什么这会使向量不起作用?它可能需要一个自定义分配器,但我对此表示怀疑。

标签: c++ arrays constructor initialization


【解决方案1】:

你们太复杂了。当然,您可以在 C++ 中执行此操作。为了效率,他使用普通的阵列就可以了。向量只有在事先不知道数组的最终大小时才有意义,即它需要随着时间的推移而增长。

如果您可以知道链中更高一级的数组大小,那么模板类是最简单的,因为没有动态分配,也没有内存泄漏的可能性:

template < int ARRAY_LEN > // you can even set to a default value here of C++'11

class MyClass
  {   
  int array[ARRAY_LEN]; // Don't need to alloc or dealloc in structure!  Works like you imagine!   
  }

// Then you set the length of each object where you declare the object, e.g.

MyClass<1024> instance; // But only works for constant values, i.e. known to compiler

如果你不知道你声明对象的地方的长度,或者你想重复使用不同长度的同一个对象,或者你必须接受一个未知的长度,那么你需要在你的构造函数中分配它并且在你的析构函数中释放它......(理论上总是检查以确保它工作......)

class MyClass
  {
  int *array;

  MyClass(int len) { array = calloc(sizeof(int), len); assert(array); }   
  ~MyClass() { free(array); array = NULL; } // DON'T FORGET TO FREE UP SPACE!
  }

【讨论】:

  • 这是对模板的错误使用。我听从了你的建议,在我的课堂上添加了一个数组长度模板,但现在我的链接器对我大喊大叫。模板类需要完全内联在标头中,或者我必须为我曾经使用的每个数组长度为类中的每个方法签名制作新的模板版本。我现在想 -1 这个答案,但显然我的投票现在被锁定了......
  • 这是一种可能的方式,但它很难与动态转换一起使用,并且除非每个案例都被显式实例化,否则会阻止使用源文件。如果需要不使用动态内存分配的向量,自定义分配器或使用像嵌入式模板库这样的库可能会有所帮助。
  • 谢谢;我一直在到处寻找这样的答案。在某些情况下,这正是我们所需要的
【解决方案2】:

您不能使用在编译时无法计算的非常量维度来初始化数组的大小(至少在当前的 C++ 标准 AFAIK 中没有)。

我建议使用std::vector&lt;int&gt; 而不是数组。它为大多数操作提供了类似数组的语法。

【讨论】:

  • 在这种情况下使用向量的语法是什么样的?
  • 向量数组;类(x):数组(x){};
【解决方案3】:

使用 new 运算符:

class Class
{
   int* array;
   Class(int x) : array(new int[x]) {};
};

【讨论】:

  • 如果使用此代码,请不要忘记在构造函数中调用 delete[]。
  • 如果这样做,您还需要一个复制构造函数、一个赋值运算符和一个析构函数。使用 std::vector 为您提供完全相同的功能,但不需要这些。
  • +1 这实际上通过初始化数组的大小来回答 OP 的问题,尽管它实际上是用构造函数中的列表替换不是数组的int *array。 @(anon) 除了复制构造函数、赋值运算符和析构函数之外,这确实回答了问题。
【解决方案4】:

我认为这是不可能的。至少不是你想要的方式。当大小来自动态信息 (x) 时,您无法创建静态大小的数组 (array[])。

您需要存储指向 int 的指针和大小,并重载复制构造函数、赋值运算符和析构函数来处理它,或者使用 std::vector。

class Class
{
  ::std::vector<int> array;
  Class(int x) : array(x) { }
};

【讨论】:

    【解决方案5】:

    你不明白没有必要使用向量,如果一个人想使用数组,那是一个效率问题,例如更少的空间,没有复制时间(在这种情况下,如果处理得当,甚至不需要在析构函数中删除数组)等等。不管是什么原因。

    正确答案是:(引用)

    class Class
    {
       int* array;
       Class(int x) : array(new int[x]) {};
    };
    

    不要试图强迫一个人使用非最佳替代方案,否则你会迷惑没有经验的程序员

    【讨论】:

      【解决方案6】:

      很抱歉破坏了这个旧线程。 实际上有一种方法可以找出数组编译时的大小。它是这样的:

      #include <cstdlib>
      
      template<typename T>
          class Class
          {
              T* _Buffer;
      
              public:
              template<size_t SIZE>
                  Class(T (&static_array)[SIZE])
                  {
                      _Buffer = (T*)malloc(sizeof(T) * SIZE);
      
                      memcpy(_Buffer, static_array, sizeof(T) * SIZE);
                  }
      
                  ~Class()
                  {
                      if(_Buffer)
                      {
                          free(_Buffer);
                          _Buffer = NULL;
                      }
                  }
          };
      
      int main()
      {
          int int_array[32];
          Class<int> c = Class<int>(int_array);
      
          return 0;
      }
      

      或者,如果您讨厌 malloc / new,那么您可以创建一个 size 模板类。不过,我不会真的推荐它,而且语法很丑。

      #include <cstdio>
      
      template<typename T, size_t SIZE>
          class Class
          {
              private:
                  T _Array[sz];
              public:
                  Class(T (&static_array)[SIZE])
                  {
                      memcpy(_Array, static_array, sizeof(T) * SIZE);
                  }
          };
      
      int main()
      {
          char int_array[32];
          Class<char, sizeof(int_array)> c = Class<char, sizeof(int_array)>(int_array);
          return 0;
      }
      

      无论如何,我希望这会有所帮助:)

      【讨论】:

      • 在 C++11 中,确定内置数组大小的一种优越方法是使用 constexpr 模板函数。例如: template constexpr std::size_t size( const T (&array)[N] ) { return N; }
      【解决方案7】:

      为什么不使用原始数组,而不是使用向量。

      class SomeType {
        vector<int> v;
        SomeType(size_t x): v(x) {}
      };
      

      使用向量将在遇到异常时为您提供自动泄漏保护以及与原始数组相比的许多其他好处。

      【讨论】:

      • 你的意思是“使用矢量会给你自动泄漏保护”吗? :)
      • @mkb,这是我今天做了两次根本上愚蠢的 cmets。在我开始发帖之前必须喝更多的咖啡才能醒来;)
      【解决方案8】:

      我遇到了同样的问题,我是这样解决的

      class example
      {
        int *array;
      
        example (int size)
        {
          array = new int[size];
        }
      }
      

      【讨论】:

        【解决方案9】:

        就像已经建议的那样,矢量是大多数情况下的不错选择。

        或者,如果要避免动态内存分配并且在编译时已知最大大小,则可以将自定义分配器与 std::vector 一起使用,或者可以使用嵌入式模板库之类的库。

        请看这里:https://www.etlcpp.com/home.html

        示例类:

        
        #include <etl/vector.h>
        
        class TestDummyClass {
        public:
            TestDummyClass(size_t vectorSize) {
                if(vectorSize < MAX_SIZE) {
                    testVector.resize(vectorSize);
                }
            }
        
        private:
            static constexpr uint8_t MAX_SIZE = 20;
            etl::vector<int, MAX_SIZE> testVector;
            uint8_t dummyMember = 0;
        };
        

        【讨论】:

          【解决方案10】:

          您不能在 C++ 中执行此操作 - 请改用 std::vector:

          #include <vector>
          
          struct A {
             std::vector <int> vec; 
             A( int size ) : vec( size ) {
             }
          };
          

          【讨论】:

            【解决方案11】:

            将数组声明为指针。您可以稍后通过 new 在初始化器列表中对其进行初始化。

            最好使用未知大小的向量。

            您可能还想查看this question 以及可变长度数组。

            【讨论】:

            • 最好也使用已知大小的向量
            • 坏主意。在存在异常的情况下,对像数组一样的指针进行内存管理并非易事。使用 std::vector 或 std::tr1::array。
            • 已接受,但这只是针对原始问题的一个选项
            猜你喜欢
            • 1970-01-01
            • 2014-08-02
            • 1970-01-01
            • 2021-11-10
            • 2011-05-02
            • 1970-01-01
            • 2014-10-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多