简体   繁体   中英

Getting 'Non-constant expression as array bound' when field is const

I'm trying to define a multidimensional array using my constant field as its dimension, but I'm getting a compilation error saying that the expression is not constant. Is there any other way to do this so I can use a constant field defined in constructor initialization list as an array dimension?

Translation for English-speaking majority:

class FunctionWave2D : public DisallowedDomainPoints
{
protected:
    double th; 
    double l; a
    double d, dd; 
    const int number_sqrt;  //here's the constant

    double **second_derivatives;

protected:
    bool elasticTenstionOnly;

public:
    FunctionWave2D(int number, double elasticModulus, double dampingFactor, double oscillationDampingFactor, double length)
        :DisallowedDomainPoints(number * LAYER_COUNT),
        th(elasticModulus), d(dampingFactor), dd(oscillationDampingFactor),
        elasticTensionOnly(false),
        l(length/(sqrt(number)-1)),
        number_sqrt(sqrt(number))
    {   
        second_derivatives = new double[number_sqrt][number_sqrt][LAYER_COUNT];
//(...)

An array bound has to be a compile-time constant. A non-static const data member is not a compile-time constant; it gets its value at runtime, when the object is constructed.

So, basically, if you need to set the size of that array at runtime you'll have to build up all the pieces with operator new[] . Essentially,

int **data_2d = new int*[runtime_size];
for (int i = 0; i < runtime_size; ++i)
    data_2d[i] = new int[runtime_size];

The extension to a 3d-array is straightforward.

In C++, the term "constant expression" specifically refers to an expression whose value is known at compile-time. It's not the same as a const variable. For example, 137 is a constant expression, but in this code:

int function(int x) {
    const int k = x;
}

The value of k is not a constant expression, since its value can't be determined at compile-time.

In your case, you have a data member declared as

 const int ilosc_sqrt;  //here's the constant

Even though this is marked const , its value is not known at compile-time. It is initialized in the initializer list as

ilosc_sqrt(sqrt(ilosc))

This value can't be determined until the program is actually run, hence the error. (Note that the new C++11 constexpr keyword is designed, among other things, to make constant expressions a lot easier to identify in source code and to make it possible to do more advance compile-time computations with constants.)

To fix this, you will either need to split up your initialization into smaller steps:

drugie_pochodne = new double**[ilosc_sqrt];
for (int i = 0; i < ilosc_sqrt; i++) {
    drugie_pochodne[i] = new double*[ilosc_sqrt];
    for (int j = 0; j < ilosc_sqrt; j++) {
        drugie_pochodne[j] = new double[ILOSC_WARSTW];
    }
}

Or use a library like Boost.MultiArray, which supports a cleaner initialization syntax.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM