инициализация массива, ссылка на предыдущий элемент в порядке? - PullRequest
9 голосов
/ 06 ноября 2010
const QPointF points[] =
{
    QPointF(r.left() - i, r.top() - i),
    QPointF(r.right() + i, r.top() - i),
    QPointF(r.right() + i, r.bottom() + i),
    QPointF(r.left() - i, r.bottom() + i),
    points[0] // is this line valid (according to the C++ standard)?
};

Хотя это компилируется с помощью компилятора MS Visual Studio, я не уверен, является ли это допустимым кодом в соответствии со стандартом C ++.

Цитаты из стандарта будут высоко оценены.

Ответы [ 4 ]

3 голосов
/ 11 сентября 2011

C ++ 03 / C ++ 11 ответ


Нет, это не так.

На правой стороне =, points существует 1 , но инициализатор применяется только после того, как все его операнды вычислены.

  • Если points находится в области пространства имен (и, таким образом,имеет статическую длительность хранения и инициализируется нулями 2 ), тогда это "безопасно", но использование points[0] там даст вам 0, а не QPointF(r.left() - i, r.top() - i) снова.

  • Если points имеет автоматическую продолжительность хранения - она ​​еще не была инициализирована, поэтому вы используете points[0], пытаясь использовать неинициализированную переменную, где points[0] имеет неопределенное значение... что плохо 3 .

Для этого сложно дать стандартные ссылки, кроме как сказать, что в 8.5 "Initializers" нет ничего, что явно делает этовозможно, и правила в другом месте заполнить остальные.


1 [n3290: 3.3.2/1]: Точка объявленияимя сразу после его полного декларатора (пункт 8) и до его инициализатора (если есть), за исключением случаев, указанных ниже.[ Пример:

int x = 12;
{ int x = x; }

Здесь второй x инициализируется своим собственным (неопределенным) значением. - конец примера ]

2 [n3290: 3.6.2/2]: Переменные со статической продолжительностью хранения (3.7.1) или продолжительностью хранения потока (3.7.2) должны быть инициализированы нулями(8.5) перед любой другой инициализацией.[..]

3 [n3290: 17.6.3.3/2]: [..] [ Примечание: Операции с неопределенными значениями могут вызывать неопределенное поведение. - конец примечания ]

2 голосов
/ 06 ноября 2010

от http://www.comeaucomputing.com/pcgi-bin/compiler.cgi:

Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 8: warning: variable "points" is used before its value is set
      points[0] // is this line valid (according to the C++ standard)?
0 голосов
/ 11 сентября 2011

Поскольку в выражении нет последовательности , результат не определен, как и в примере i=i++, приведенном на этой странице википедии.

В противном случае ничего не указано,должен ли компилятор сначала все оценивать, а затем присваивать или делать оценку-присваивание для каждого элемента отдельно и в каком порядке.

0 голосов
/ 12 ноября 2010

Старый ответ (пропущено):

Я проверил текущий черновик C ++ 0x, и там я нашел предложение 8.5.1.17, которое гласит:

17 Полные выражения в initializer-clause оценивается в порядок, в котором они появляются.

Так что, хотя это предложение не является частью стандарта C ++ от 2003 года, я совершенно уверен, что это должно работать в любом современном компиляторе, если это является частью C ++ 0x.

Edit:
Комментарии заставили меня переосмыслить этот вопрос. Эта строка гарантирует, что объекты QPointF создаются в том порядке, в котором они встречаются при инициализации массива (актуально, если конструкторы элементов имеют наблюдаемые побочные эффекты). Проблема в том, что значение points является неопределенным во время инициализации массива. Таким образом, гарантия действительного значения points[0] также не может быть гарантирована, по крайней мере, если вы полагаетесь на стандарт.

...