Является ли доступ к одному элементу в объединении, скопированном из объединения с другим набором элементов, неопределенным или неопределенным?

Рассмотрим следующий фрагмент кода, предполагая, что A и B являются тривиальными типами одинакового размера, скажем, int64_t и double, или что-то подобное:

union Punner {
  A x;
  B y;
};

Punner copy(Punner in)
{
  return in;
}

A pun(B in)
{
  Punner temp;
  temp.y = in;
  return copy(temp).x;
}

Хотя я знаю, что строка temp.y = in запускает время жизни члена y из temp, и чтение temp.x будет неопределенным, когда я получаю новую копию типа Punner из функции copy, если предположить, что время жизни копии y члена также равно уже запущен, и чтение элемента x копии все еще не определено, или оно просто не указано, и после получения копии я действительно могу свободно читать либо из x, либо из y (в данном случае чтение из x)?

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


person markt1964    schedule 22.11.2019    source источник
comment
По правде говоря, промежуточная копия не имеет значения.   -  person Deduplicator    schedule 23.11.2019
comment
Возможно дублирование: stackoverflow. ком/вопросы/11373203/   -  person Eljay    schedule 23.11.2019


Ответы (1)


Вы должны думать о том, что на самом деле происходит в памяти.

Punner temp; //data in memory could be anything

temp.y = in; //data contains 8 bytes that describe an integer with the value in

copy(temp); //the copied data is 8 bytes that describe an integer with the value in

copy(temp).x; //accessing those 8 bytes as if they describe a double : getting giberish.
person iliar    schedule 22.11.2019
comment
Очевидно, что возвращаемое число будет тарабарщиной, но я спрашиваю, являются ли результаты неопределенными или неопределенными. - person markt1964; 23.11.2019
comment
Да, я имел в виду 8. Что вы имеете в виду, если это не указано или не определено? Эти два слова кажутся синонимами. Я описал вам, что на самом деле будет происходить в памяти для любого известного мне компилятора. - person iliar; 23.11.2019
comment
@ markt1964 markt1964 в некоторых случаях я фактически использовал его для доступа к битам числа с плавающей запятой для их преобразования непосредственно в числа с фиксированной запятой. - person iliar; 23.11.2019
comment
Это не совсем синонимы. Неопределенное поведение — это то, чего следует избегать всегда, но неопределенное поведение не обязательно будет плохим, просто результаты не указаны. - person markt1964; 23.11.2019
comment
@markt1964 markt1964 Думаю, и то, и другое подразумевает тарабарщину. Вы никогда не получите синий экран, потому что память выделена. Хотя компилятор может генерировать некоторые оптимизации, если у вас есть одно поле размером 4 байта, а другое — 16, и компилятор видит только присвоение 4 байтам. Но поскольку он видит доступ к 16 байтам, я думаю, он не будет оптимизировать его таким образом. - person iliar; 23.11.2019
comment
Я специально рассматривал только случаи, когда A и B имеют одинаковый размер. Очевидно, что если они будут разного размера, это будет очень плохо. Кроме того, поведение Undefined может вызывать сбой. Может и нет, но может. Неопределенное поведение — это просто неопределенное поведение. В моем случае я спрашиваю, кто из участников, x или y, не спит в ответном сообщении от copy? Или это не указано? - person markt1964; 23.11.2019
comment
@ markt1964 В таком случае это определенно y. Доступ к y явно правильный. x - это тот, который не определен/не указан. - person iliar; 23.11.2019
comment
@iliar Unspecified и undefined очень разные и чтение члена объединения, который не active вызывает неопределенное поведение, поэтому компилятор может позволить программе завершиться сбоем или сделать все, что он хочет. Выполнение этого для каламбура с плавающей запятой для целых чисел также является UB в C++. Это может работать, потому что ваш компилятор дает эту дополнительную гарантию, но при этом не требуется, чтобы компилятор C++ вел себя должным образом. - person walnut; 23.11.2019
comment
Но я спрашивал, есть ли у кого-то свежая копия союза, который был скопирован откуда-то еще, определен ли явно активный член всегда таким же, как союз, из которого он был скопирован, или он просто не указан? - person markt1964; 25.11.2019
comment
@ markt1964 markt1964 да, он определен как тот же активный член, что и объединение, из которого он был скопирован. Это совершенно законно c/С++. - person iliar; 25.11.2019
comment
@ markt1964 markt1964 На самом деле, это причина ограничений объединения, включающего члены с нетривиальными конструкторами. см.: en.cppreference.com/w/cpp/language/union - person iliar; 25.11.2019
comment
@iliar Нет, это не очень четко определено даже в C ++ 17 (хотя это явно должно быть так, как вы говорите), поэтому в текущий самый последний черновик, который вы можете найти в Интернете, добавлена ​​​​дополнительная формулировка, уточняющая, что неявная копия конструктор фактически начинает время жизни правильного активного члена. open-std.org/ jtc1/sc22/wg21/docs/papers/2019/ - person JMC; 06.09.2020