【问题标题】:Declaring an object's array size in the class在类中声明对象的数组大小
【发布时间】:2013-11-29 11:31:45
【问题描述】:

当我尝试填充我的数组时收到“分段错误”。所以我想在类中声明数组大小来声明数组的大小以便它可以分配空间,但我收到了。

错误:无效使用非静态数据成员“Array::Size”错误:来自 这个位置

//Current
class Array{
    public:
    int Size;
    int Range;
    int Array[];
};


//Problematic 
class Array{
    public:
    int Size;
    int Range;
    int Array[Size];
};

或者还有其他防止分段错误的方法吗?

【问题讨论】:

    标签: c++ arrays class segmentation-fault


    【解决方案1】:

    您正在尝试使用 C 习惯用法,其中结构的最后一个成员是一个非常短的数组(一个,或者,如果编译器允许作为非标准扩展,零元素)并且为结构分配了额外的内存因此可以访问声明数组末尾之外的元素。这最初是一个非标准技巧,称为struct hack,或在某些编译器中称为zero-length arrays。它在 C99 中被标准化为 flexible arrays

    当你使用这个习语时,你需要为数组分配额外的内存,例如sizeof (struct Array) + sizeof (int) * number_of_elements。否则,您不会为比实际声明更多的元素分配内存(通常为 1 或 0),并且当您尝试访问超出该范围的元素时,您会得到未定义的行为。

    但是,您正在编写 C++,而不是 C99。即使你的编译器允许你这样做,依赖它也是非常糟糕的做法,而且 C++ 比 C 更尴尬。

    要么在类中存储一个指针并在构造函数中分配适当数量的内存,然后在析构函数中释放它,或者使用将为您管理内存的 C++ 类,例如std::vector.

    这里是一个使用std::vector的例子:

    #include <vector>
    
    class Array{
        public:
            int size;
            int range;
            std::vector<int> array;
    
            Array(int size, int range) :
                size( size ),
                range( range ),
                array( size, 0 )
            {
            }
    };
    

    【讨论】:

    • @Constantin 不,int Array[]; 不是声明int* 的有效方式。您的代码似乎无法为我编译。见here
    • 在C99中称为“弹性数组”。 “零长度”类似于int a[0],它从来都不是标准的,只能作为某些编译器的扩展使用。
    • @KerrekSB 试图澄清一下,更好吗?在 C99 之前,我的理解是该技巧是非标准的,但仍在广泛使用,尽管可能是 int a[1] 而不是 int a[0]
    • @svk:所以,int a[1] 实际上是标准的,虽然分配和访问更多内存不是(在 C89 中)——但你总是需要处理烦人的问题——一。我相信int a[0](严格来说是一个结构成员!)被一些编译器接受以克服一对一的问题,并最终在C99中标准化为int a[]...
    • @KerrekSB 好吧,当然,int a[1] 始终是作为单个元素数组声明的标准,但如果实际上不允许访问 a[1],这似乎是一种技术性问题在分配了一些额外的内存之后。
    【解决方案2】:

    这两个定义

    //Current
    class Array{
    public:
    int Size;
    int Range;
    int Array[];
    };
    //Problematic 
    class Array{
    public:
    int Size;
    int Range;
    int Array[Size];
    };
    

    无效。第一个无效,因为类定义可能不包含不完整的非静态数据成员。你不能写 int Array[]; 第二个无效,因为 1) 数据成员 Size 具有未定义的值和 2) 数组的大小应为常量表达式。 您可以使用指针并动态分配所需大小的数组,而不是声明数组。

    【讨论】:

      【解决方案3】:

      你可以使用指针。

      class Array{
      public:
      int Size;
      int Range;
      int* Array;
      };
      

      在构造函数中,你可以为它分配内存。或者您可以在成员函数中执行此操作。

      Array::Array(/*parameters*/){
      /* code */
      Array = new int [Size] //After Size is initialized or assigned.
      }
      

      在析构函数中,你应该使用delete[] Array来释放内存。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-14
        • 1970-01-01
        • 1970-01-01
        • 2013-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多