2009-06-20 4 views
1

Я хочу сравнить объекты класса/структуры C++. В C большую часть времени вы знаете точный размер struct, добавляя размеры отдельных полей (предполагая, что компилятор не добавляет отступы). Следовательно, можно использовать функцию memcmp() на двух объектах, чтобы сравнить их очень быстро. Я не уверен, что то же самое работает для C++. Это потому, что класс также определение функций и, возможно, некоторые другие скрытые вещи (некоторая RTTI информация может быть? Таблица виртуальной функции даже?)Сравнение структур в C vs C++

Быстрой программа с простой структурой, содержащей int и char членов и функцию показала, что размер от структуры sizeof(int)+sizeof(char).

У меня есть один большой класс структуры с простыми типами данных int, char и т. Д. (Но их большое количество). Я хочу время от времени сравнивать объекты. Я не могу перегрузить оператора ==, так как это позволит им сравнивать каждое поле по полю. В C я могу сравнить за один раз, используя memcmp(). Любые предложения для C++? Могу ли я использовать memcmp() напрямую? Я не хочу memcmp(), чтобы не потому, что некоторое другое значение, как виртуальная таблица указателей функции отличается (но все поля фактически равны) (я использую г ++)

+1

Учитывая несоответствующую упаковку (например, struct z {x char; y double;};), вы получите заполнение в C-структурах. Было бы глупо предположить, что в целом нет прокладки, хотя вы можете свести к минимуму вероятность того, что это произойдет, если вы будете осторожны. –

ответ

10

Будьте осторожны по многочисленным подсчетам ...

  1. Значения в любой прокладке являются неопределенными и, следовательно, не сопоставимы.
  2. Если ваша машина малозначительна, сравнение целых полей даст один ответ; если ваша машина большая, это даст другой ответ.
  3. Большинство людей считают -1, как меньше 0, но memcmp() будет делать побайтно беззнаковое сравнение, и, следовательно, будет относиться к -1, как больше, чем 0.
  4. Любые указатели по своей сути не сопоставимы релевантно по memcmp().
  5. Вы не можете сравнить float или double используя memcmp().

В целом, вы ищете неразумную оптимизацию.

+1

+1 для этого: «вы ищете неразумную оптимизацию».Но FYI вы * можете * сравнить float и double с помощью memcmp; равные числа - это равные битовые шаблоны. – Crashworks

+1

+1 полезные сравнения поплавков лучше оставить на fpu – SingleNegationElimination

+0

@Crashworks: Большинство реализаций fp, включая IEEE754, имеют отдельную концепцию +0.0 и -0.0. Большинство людей будут считать эти значения равными, и во многих случаях система времени выполнения будет пытаться сравнить их как равные. однако они имеют разные битовые шаблоны. – SingleNegationElimination

3

Если ваш class или struct не имеет ничего виртуального, " добавляя размеры отдельных полей (и предполагая, что компилятор не добавляет отступы) »примерно так же корректно в C++, как и в C (т. е. не полностью, потому что добавление равно;

9

Можно взять sizeof() структуру или класс.

редактировать: , поскольку я представил выше ответ, вы изменили свой вопрос с «Как я могу вручную определить размер структур и классов C++?» к более общей для сравнения двух классов.

Короткий ответ, что вы do хотите перегрузить == оператора. Вера в то, что он будет сравнивать каждое поле по полю один за раз, неверен; вы можете перегрузить operator ==, чтобы использовать любой алгоритм, который вам нравится, включая memcmp.

memcmp() в памяти от первого смещения поля до последнего должно работать нормально. A memcmp() на весь след класса может потерпеть неудачу, если вы сравниваете класс типа A с другим классом B, который наследуется от A, поскольку указатели vtable могут быть разными.

+0

Это гарантированно работает? Например, если у меня есть класс {int a; long b; char c; }; Могу ли я написать следующее Перегрузка оператора func (B) { int byte_cmp = & this.c - this.a + sizeof (this.c); return memcpy (& this.a, & B.a, bytes_to_cmp); } – Methos

+0

Да, хотя вы, вероятно, этого не хотите. Поля, конечно же, всегда будут одинакового размера и порядка для каждого экземпляра класса. Будьте осторожны, чтобы бросить & this.a и & this.c на BYTE *, конечно, чтобы ваша арифметика указателя работала правильно. Однако, честно говоря, это не нужно, потому что то, что у вас есть, - это то, что сам компилятор g ++ будет выдавать как оператор по умолчанию == для любого класса, состоящего исключительно из примитивных типов. – Crashworks

+2

Нет; Функция memcmp() не гарантируется. Не гарантируется работа на одной машине, даже для структур POD; он, безусловно, не гарантированно работает в переносном режиме через машины. –

3

P.O.D s безопасен для сравнения с memcmp.

Padding - проблема для создания memcmp объектов класса, поскольку он может быть заполнен мусором (который будет отличаться от объекта к объекту). В C у вас обычно нет этой проблемы, потому что в общем случае нормально помещать всю структуру в 0 до того, как вы выполните какое-либо задание, и это очень плохо в C++, потому что вы можете перезаписать vtable.

Я не верю, что в спецификации языка есть что-то, что говорит о том, как реализуются vtables, хотя они обычно являются членом данных с hidded. Vtable должен быть одинаковым для членов одного класса (но, конечно, будет отличаться для родительских/дочерних классов). Когда вы получаете множественное или виртуальное наследование, реализация может быть даже более разнообразной от компилятора к компилятору.

+1

POD небезопасны для сравнения с memcmp. Значения байтов заполнения не определены. В этом случае ints в принципе небезопасно сравнивать с memcmp, потому что не все биты в представлении хранилища обязательно участвуют в представлении значений. POD можно скопировать с помощью memcpy, но это не то же самое, что сопоставимо с memcmp. –

0

Насколько мне известно, вы можете предотвратить заполнение в структурах с помощью #pragma пакета (gcc, vc++)

#pragma pack(push, 1) 
struct Example 
{ 
    int a; 
    char b; 
    short c; 
}; 
#pragma pack(pop) 

печати SizeOf (пример) показывает, что 7 байт. Без пакета #pragma размер составляет 8 байтов.

+1

7 байтов, а по некоторым архитектурам доступ к c приводит к неопределенному поведению ... –

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