C++ const используется дважды в объявлении статического массива

Я видел const используется дважды в объявлении static массив раньше и теперь, когда я создаю свой собственный статический массив, мне интересно, почему const понадобится дважды в некоторых ситуациях.

имеет ли значение наличие массива указателей?

a. static const TYPE name[5];
b. static const TYPE const name[5];

c. static const TYPE* name[5];
d. static const TYPE* const name[5];

насколько я понимаю, это b. недопустимо, но если использование const дважды допустимо, какова его цель?

4 ответов


const тип* x;

означает, что вещь, на которую указывает x, является const.

тип * const x;

означает, что указатель x является const.

объединение 2 Вы получаете:

const тип * const x;

означает, что указатель и указанная вещь являются const.


вы можете применить любой CV-квалификатор (const или volatile) к любому типу, включая CV-квалифицированные типы -- но не в таком же объявлении. Однако они связываются сильнее, чем любой оператор, с точки зрения приоритета и могут применяться с обеих сторон квалифицированного типа:

// Let T by any type:
T const tr;
const T tl;
const T const tlr; // only in C
const const const const const T t5; // only in C
typedef const T CT;
CT const tcc; // fine, although CT was already const

объявить то же самое, константа T. Если T уже есть cv-квалификаторы, это не меняет значения дополнительной квалификации.

теперь к старшинству; вы можно сказать: "я хочу указатель на константу T":

const T (* tp);

который обычно пишется как

const T* tp;

потому что const связывает сильнее, чем * в любом случае. В том же шаблоне вы можете определить переменную, которая является "константой, но указывает на изменяемый T":

T (* const tp) = 0; // must be initialised, because tp is immutable

который обычно пишется как

T* const tp = 0;

в том же ключе оператор индекса [] применяется -- с тем же приоритетом, что и в выражения.


в первом блоке кода у вас есть дублирующие const во второй строке, которая не имеет никакого эффекта. (На самом деле, хорошие компиляторы предупредят вас об этом.) Вы объявляете массив из 5 const TYPEs, Вот и все.

второй блок кода имеет два различных сценария: первая строка создает массив из пяти mutable указатели const TYPEs, в то время как последний делает массив из пяти постоянный указатели const TYPEs.

обратите внимание, что вы должны инициализировать массив констант: поскольку вы не можете изменить значения позже, нет смысла определять их неинициализированными.


используя const дважды на типе является незаконным в C++ 2003, но законным в C++ 2011 (см. 7.1.6.1 [decl.типа.cv] пункт 1: "избыточные cv-квалификации игнорируются."). Когда вы используете

static const TYPE const name[5];

ты TYPE дважды постоянной. Обратите внимание, однако, что это объявление является незаконным и в C++ 2011, потому что вам нужно инициализировать const объект при его декларировании. Смысл

const TYPE

и

TYPE const

абсолютно эквивалентно: в обоих случаях вы делаете TYPE объект постоянным. Для согласованности я всегда ставлю const вправо, потому что каждый, кроме верхнего уровня типа const должен быть поставлен на правую сторону (ну, если некоторые руководящие принципы кодирования не требуют по-другому, но я борюсь с глупыми руководящими принципами кодирования).

при использовании указателей, думает, что стал другим. Существует два типа: Тип, указываемый на тип, и указатель. Каждый из них может быть сделан const отдельно:

TYPE const*       ptr1(0);  // non-const pointer to const TYPE
TYPE* const       ptr2(0);  // const pointer to non-const TYPE
TYPE const* const ptr3(0);  // const pointer to const TYPE

лучший способ выяснить, что это сделал const читать объявление типа справа налево. Конечно, это предполагает, что const спецификаторы помещаются в нужное место. Вы можете заменить const by volatile или const volatile в обсуждении выше и то же самое рассуждение применяется.