C ++ Порядок декларирования (в строке с несколькими переменными) - PullRequest
0 голосов
/ 10 декабря 2018

Я использую следующее в своем коде C ++:

int a = 0, b = a;

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

Если не надежно, я бы нарушил утверждение:

int a = 0; 
int b = a;

Спасибо.

Ответы [ 3 ]

0 голосов
/ 10 декабря 2018

Я полагаю, что ответ - нет.

Он подлежит активной активной проблеме 1342 , в которой говорится:

Не ясно, что, если что-нибудьв существующей спецификации требуется, чтобы инициализация нескольких init-деклараторов в пределах одного объявления выполнялась в порядке объявления.

У нас есть ненормативное примечание в [dcl.decl] p3 , в котором говорится:

... [Примечание: объявление с несколькими деклараторами обычно эквивалентно соответствующей последовательности объявлений, каждая с одним декларатором.То есть

T D1, D2, ... Dn;

обычно эквивалентно

T D1; T D2; ... T Dn;

...

, но это ненормативно и не охватывает случай инициализациивообще, насколько я могу судить, ни одна нормативная формулировка не говорит о том же.

Хотя стандарт действительно охватывает область имен в [basic.scope.pdecl] p1 , которая гласит:

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

unsigned char x = 12;
{ unsigned char x = x; }

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

0 голосов
/ 15 декабря 2018

Оператор объявления, который определяет несколько переменных, разделенных запятой, в точности эквивалентен множеству операторов объявления, которые определяют одну переменную в том же порядке, поскольку область действия переменной начинается сразу после ее имени, но есть (как минимум) два исключения :

1) Когда объявление переменной скрывает тип с тем же именем, как в:

struct S {};
S S, T;

Отличается от

struct S {};
S S;
S T; //error: S is a variable name

Но

struct S {};
S S, T{S};

Эквивалентно

struct S{};
S S;
struct S T{S};

2) При использовании auto и decltype(auto) спецификаторы:

auto i{0}, j{i}, k{2.0}; // error: deduction for auto fails, double or int?

Отличается от

auto i{0};
auto j{i};
auto k{2.0};

В любом случае порядок оценки всегда слева направо.

0 голосов
/ 10 декабря 2018

Тот факт, что вы решили задать этот вопрос, говорит о том, что стиль не велик.Даже при том, что однострочная версия почти гарантированно работает, я все равно предпочел бы двухстрочный подход для большей ясности для читателей.


Сначала я сказал, что это гарантировано, но я отступлю от этого.Изучив соответствующую часть спецификации, я вижу, как языковые юристы будут жаловаться на то, что эта гарантия прямо не указана.(Как указывает Шафик Ягмур, основной активный выпуск 1342 отмечает отсутствие явной гарантии, хотя и с формулировкой, предполагающей, что такая гарантия должна присутствовать.)

Я сделаю только шаг назадк «почти гарантированному», однако, как это строго следует из « Каждый init-декларатор в объявлении анализируется отдельно, как если бы он был в объявлении сам по себе. ».То есть, анализ int a = 0, b = a; состоит из двух частей: одна, где переменная с именем a инициализируется как 0, и другая, где переменная с именем b инициализируется до значения a.Если вы действительно храните эти части отдельно, то первая часть должна быть закончена до начала второй части (иначе они не будут такими, как если бы каждая была в объявлении сама по себе), поэтому a будет иметь значение 0 передb инициализируется.Я принимаю, что это может быть недостаточно определенно для юристов, изучающих язык, но оно должно быть достаточно для отчета об ошибках компилятора, если есть компилятор, для которого эта строка не работает должным образом.

Мои извинения за то, что нетищем спецификацию раньше.Тег «language-lawyer» отсутствовал при первом ответе.

...