В С++, что означает доступ в строгом правиле псевдонимов?

3.10/10 говорит:

Если программа пытается получить доступ к хранимому значению объекта через значение gl, отличное от одного из следующих типов, поведение не определено:

Однако термин «доступ» нигде не определен. В данном контексте это означает прочитать или прочитать или изменить?


В стандарте C это однозначно определяется как чтение или изменение. Однако в С++ 11 он, кажется, используется в разных значениях в разное время, например:

1.9/8:

Доступ к volatile-объектам оценивается строго по правилам абстрактной машины.

Ясно, что это предназначено для чтения или изменения, однако во многих других местах, таких как 1.10/24:

  • получить доступ или изменить изменчивый объект, или

он используется так, как будто он означает только чтение.


person M.M    schedule 12.03.2015    source источник
comment
Вы можете сократить заголовок до: Что означает «доступ» в C++? Это большой вопрос. (Конечно, что касается строгого правила псевдонимов, намерение, безусловно, читается или изменяется, как и в C.)   -  person Nemo    schedule 12.03.2015
comment
@Nemo Согласен, хотя меня больше всего интересует именно этот случай. Возможно, это отдельный вопрос.   -  person M.M    schedule 12.03.2015
comment
Ну, независимо от их намерений в этом разделе, они определенно не заявили об этом ясно, поэтому я бы сказал, что вы определенно нашли ошибку в спецификации.   -  person Nemo    schedule 12.03.2015
comment
Стандарт, как известно, плохо справляется с такими вещами. Даже такой ярый юрист, как я, избегает таких вопросов, как чумы. Ты сам по себе ;)   -  person Lightness Races in Orbit    schedule 12.03.2015
comment
@LightnessRacesinOrbit, хех. Проблемы со строгим алиасингом достаточно ужасны, чтобы их можно было решить без этой двусмысленности. Я всегда предполагал, что это должно быть как в C; но я читал несколько других ответов о строгом псевдониме (особенно в отношении объединения с новым размещением), и все они молчаливо полагаются на access, что означает только read, поэтому я был надеясь прояснить это, прежде чем комментировать / публиковать дальше строгие псевдонимы   -  person M.M    schedule 12.03.2015
comment
Размещение new немного странно — оно повторно использует хранилище, что завершает время жизни объекта, который был там раньше.   -  person T.C.    schedule 12.03.2015


Ответы (2)


Оно должно означать и чтение, и запись, иначе правило не имело бы большого значения. Рассмотрим пример из http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html:

float *P;
void zero_array() {
   int i;
   for (i = 0; i < 10000; ++i)
       P[i] = 0.0f;
}

Приведенный выше пример кода можно оптимизировать в memset только в том случае, если компилятор может предположить, что ни один из P[i] псевдонимов P. Но рассмотрим мир, в котором только чтение из запрещенного glvalue является UB, тогда приведенный выше код не будет вызывать UB, даже если P[i] псевдонимы P для некоторых i — например, если кто-то сделал P = (float *) &P;, потому что все чтения числа P совершенно законны — все они используют выражение lvalue P.


Изменить: выпуск CWG 1531 прямо в точку. Проблема была переведена в статус DR (отчет о дефекте) в апреле 2013 года, но решение по какой-то причине не было применено к рабочему документу.

person T.C.    schedule 12.03.2015
comment
Отличный пример (как и ваш пример в другом комментарии) - person M.M; 12.03.2015
comment
Я не вижу никаких проблем со стандартом, указывающим, что чтение PODS перекрестного типа дает потенциально неопределенное значение, а запись PODS перекрестного типа устанавливает для него потенциально промежуточное значение, по крайней мере, если бы стандарт был более четким в отношении того, что может и не может произойти при работе с промежуточными значениями типов, которые не имеют естественных представлений-ловушек (во всяком случае, ИМХО, стандарт должен решать эту проблему). - person supercat; 29.06.2016

Я не претендую на звание языкового юриста. Однако...

Я бы интерпретировал фразу «доступ к сохраненному значению объекта» как «прочитать сохраненное значение объекта».

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

9 Если выражение может быть использовано для изменения объекта, на который оно ссылается, такое выражение называется модифицируемым. Программа, которая пытается изменить объект с помощью немодифицируемого выражения lvalue или rvalue, имеет неправильный формат.

person R Sahu    schedule 12.03.2015
comment
Судя по этому чтению, такие вещи, как int a = 0; *((short *) &a) = 100; std::cout << a;, не нарушают строгого алиасинга. В этом мало смысла. - person T.C.; 12.03.2015
comment
@Т.С. Я понимаю что ты имеешь ввиду. Есть ли что-нибудь в стандарте, где read является более строгим, чем write? - person R Sahu; 12.03.2015