Как установить размер массива с помощью переменной-члена const? - PullRequest
0 голосов
/ 18 января 2019

Я пытался установить размер массива с помощью переменной-члена const, как показано ниже

class A {
  const int SIZE;

  A() : SIZE(10) {}
  void aaa() { int a[SIZE]; }
};

Я не могу построить

а [SIZE]

как это выражение.

Когда я использую GCC, постройте успех. Но когда я использую VC ++ (Windows), я не могу собрать.

Сообщение об ошибке «this» не может использоваться в константном выражении »

Как установить размер массива с помощью переменной-члена const?

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Массивы переменной длины

когда я использую VC ++ (Windows), я не могу собрать.

В стеке создается массив int a[SIZE] с автоматической продолжительностью хранения. Тогда это SIZE обычно должно быть определено во время компиляции в C ++. Но ваш SIZE определяется без значения следующим образом:

const int SIZE;

Таким образом, компиляторы не могут знать его значение во время компиляции и будут показывать ошибку компиляции. Таким образом, ваш SIZE является динамической переменной.

Когда я использую GCC, постройте успех.

... Но некоторые компиляторы C ++ поддерживают VLA (массивы переменной длины), которые являются дополнением C99 и позволяют объявлять массивы в стиле C в стеке с динамической длиной. VC ++ не поддерживает C99 и VLA, но компилятор GNU поддерживает VLA как расширение даже в C90 и C ++ . Это причина, по которой вы можете скомпилировать приведенный выше код по GCC без ошибок.

Если вы добавите параметр -pedantic (-pedantic-errors) в команду компиляции gcc, мы можем получить предупреждения (ошибки) для большинства расширений gcc. В этом случае с этой опцией мы должны получить предупреждение (об ошибке): ISO C++ forbids variable length array 'a'.


Как исправить текущую ошибку?

(1) Если вы хотите использовать массивы в стиле C, один из способов сделать SIZE макросом следующим образом. Тогда компиляторы могут узнать его значение во время компиляции:

#define SIZE 10

class A
{
public:
  A() {}
  void aaa() { int a[SIZE]; }
};

(2) Определяя значение SIZE как переменную static const в определении класса, затем компиляторы снова могут узнать его значение во время компиляции:

class A
{
  static constexpr int SIZE = 10;

public:
  A() {}
  void aaa() { int a[SIZE]; }
};

(3) C ++ обеспечивает функциональность массивов std::vector и std::array, что может сделать наш код более читабельным, переносимым и надежным. Я ожидаю, что std::array в стеке будет более эффективным, чем std::vector в вашем случае, потому что 10 int s требует меньше памяти и std::array выделяется в стеке только один раз, не вызывая проблем. Это решение с std::array:

#include <array>

class A
{
  static constexpr int SIZE = 10;

public:
  A() {}
  void aaa() { std::array<int, SIZE> a; }
};
0 голосов
/ 18 января 2019

Ну, SIZE, вероятно, не макрос, потому что здесь вы инициализируете его с 10 и имеете его как переменную. Если бы это был макрос, ваше выражение int a[SIZE] сработало бы, но вам все равно не понадобились бы строки 2-4.

Если SIZE, как здесь, нормальная переменная (которая включает в себя динамическое создание A с параметром размера, , хотя ввод может быть из макроса), вам следует использовать вектор.

#include <vector>

class A {
  const int SIZE;

  A() : SIZE(10) {}
  void aaa() { std::vector<int> a(SIZE); }
};

Использование a теперь то же самое.

...