2010-05-21 2 views
3

Союзы - это не то, что я часто использовал, и, посмотрев на несколько других вопросов на них, кажется, что почти всегда есть какое-то предостережение, где они могут не работать. Например. структуры, возможно имеющие неожиданные дополнения или конечные различия.Является ли использование объединения в этом матричном классе полностью безопасным?

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

template<typename T> class Matrix44T 
{ 
    ... 

    union 
    { 
     T M[16]; 
     T m[4][4]; 
    } m; 
}; 

Есть ли недостатки в этой настройке? Будет ли порядок определения иметь какое-либо значение для того, как это работает?

ответ

4

Хотя я точно так же в моем Матрикс-классе я думаю, что это зависит от конкретной реализации, чтение стандарта к письму:

Standard 9.5.1:

В союзе, в лучшем случае один из данных членов может быть активным в любое время, , то есть значение не более одного из , члены данных могут быть сохранены в союзе в любое время. [Примечание: одна специальная гарантия предназначена для упрощения использования объединений: если POD-соединение содержит несколько POD-структур, которые имеют общую начальную последовательность (9.2), и если объект этого POD- union тип содержит одну из POD-структур, разрешено проверять общую начальную последовательность любого из элементов POD-структуры ; см. 9.2. ]

Вопрос состоит сделать m и M разделяют общую начальная последовательность, чтобы ответить на этот вопрос мы рассмотрим 9.2/15:

Два POD-союз (пункт 9) типы layout- совместимы, если у них есть одинаковое количество нестатических данных, и соответствующие нестатические данные. членов (в любом порядке) имеют совместимые с макетами типы (3.9).

После прочтения этого ответа, кажется, нет m и M не не макет, совместимый в строгом смысле этого слова.

На практике я думаю, что все будет работать на всех компиляторах.

+0

@Andreas - спасибо за стандартные определения. Итак, я думаю, единственное, что абсолютно гарантировано для работы, было бы две структуры с идентичным содержимым типа, но разные имена? – identitycrisisuk

+0

@identitycrisisuk Одним словом: да. –

+0

Но есть решение. Вы можете взять указатель на m [0] [0] (т. Е. & M [0] [0]), который имеет тип * T и использовать этот указатель вместо M) – Ingo

0

№ Это кажется прекрасным использованием union в соответствии с вашими предположениями.

Я бы выбрал более качественные имена, а не m и M, но кроме этого это приятное использование для union.

+0

Как раз то, что предположения не имеют никакого отношения к тому, как должен использоваться союз. – Ingo

+0

Если ваше предположение было неправильным - массив 4x4 имел разный размер, чем 16 векторных массивов, тогда он бы не сработал. – brickner

1

Если вы играете по правилам, различия в дополнениях и концах вас не повредят.

Посмотрите на этот код

union { int a; float b; } wrong; 

wrong.a = 1; 
printf("%f", wrong.b); 

Это неправильно, потому что если вы написали член «а», то любое чтение, кроме как от «а» не определено.

Подводя итог: Нельзя сказать, безопасен ли союз. Это не определение, это небезопасно, так оно и используется.

+1

@Ingo: Так технически мой пример - это неопределенное поведение? По крайней мере, чтобы написать M, а затем прочитать из m - если кто-то написал строгий компилятор, это не сработает, например. – identitycrisisuk

+0

@Ingo, Почему это не определено? Если объединение было массивом из 4 байтов, а int было законным писать как int и читать как 4 байта (с учетом соображений энтузиазма). Что это касается вопроса? – brickner

+1

@brickner - нет его нет - целое число может иметь 2 байта или 4 или 8. Или даже 7? Покажите мне стандарт, где сказано, что int должно быть 4 байта. (Это не джава, заметьте). – Ingo

Смежные вопросы