Структура объекта C ++ в памяти по сравнению со структурой

StackOverflow https://stackoverflow.com/questions/422830

  •  05-07-2019
  •  | 
  •  

Вопрос

Если у меня есть класс следующим образом

   class Example_Class 
   {
       private:
         int x; 
         int y; 
       public: 
         Example_Class() 
         { 
             x = 8;
             y = 9;
         }
       ~Example_Class() 
       { } 
   };

И структура следующим образом

struct
{
   int x;
   int y;
} example_struct;

Является ли структура в памяти example_struct аналогично тому, что в Example_Class

например, если я сделаю следующее

struct example_struct foo_struct;
Example_Class foo_class = Example_Class();

memcpy(&foo_struct, &foo_class, sizeof(foo_struct));

будет foo_struct.x = 8 и foo_struct.y = 9 (т.е.:те же значения, что и значения x, y в foo_class)?

Причина, по которой я спрашиваю, заключается в том, что у меня есть библиотека C ++ (не хочу ее менять), которая совместно использует объект с кодом C, и я хочу использовать struct для представления объекта, поступающего из библиотеки C ++.Меня интересуют только атрибуты объекта.

Я знаю, что идеальной ситуацией было бы обернуть Example_class вокруг общей структуры между кодом C и C ++, но изменить используемую библиотеку C ++ будет непросто.

Это было полезно?

Решение

Стандарт C ++ гарантии что макеты памяти C struct и C++ class (или struct -- то же самое) будут идентичны, при условии, что C++ class/struct соответствует критериям бытия СТРУЧОК ("Простые старые данные").Так что же означает POD?

Класс или структура является POD, если:

  • Все элементы данных являются общедоступными и сами являются POD или фундаментальными типами (но не ссылочными или указывающими на типы элементов), или массивами таких
  • В нем нет определяемых пользователем конструкторов, операторов присваивания или деструкторов
  • У него нет виртуальных функций
  • В нем нет базовых классов

Единственными разрешенными "C ++-измами" являются невиртуальные функции-члены, статические члены и функции-члены.

Поскольку ваш класс имеет как конструктор, так и деструктор, формально говоря, он не относится к типу POD, поэтому гарантия не действует.(Хотя, как упоминали другие, на практике эти два макета, скорее всего, будут идентичны в любом компиляторе, который вы попробуете, при условии отсутствия виртуальных функций).

См. раздел [26.7] C ++ FAQ Lite для получения более подробной информации.

Другие советы

  

Структура в памяти example_struct похожа на структуру в Example_Class

Поведение не гарантируется и зависит от компилятора.

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

В случае, который вы описываете, ответ "вероятно, да". Однако, если в классе есть какие-либо виртуальные функции (включая виртуальный деструктор, который может быть унаследован от базового класса), или используется множественное наследование, тогда компоновка класса может отличаться.

Чтобы добавить то, что сказали другие люди (например, специфичные для компилятора, они, вероятно, будут работать, если у вас нет виртуальных функций):

Я бы настоятельно рекомендовал статическое утверждение (проверка во время компиляции), что sizeof (Example_class) == sizeof (example_struct), если вы делаете это. Смотрите BOOST_STATIC_ASSERT, или эквивалентную специфичную для компилятора или пользовательскую конструкцию. Это хорошая первая линия защиты, если кто-то (или что-то, например, изменение компилятора) модифицирует класс, чтобы сделать недействительным совпадение. Если вам нужна дополнительная проверка, вы также можете проверить во время выполнения, чтобы смещения элементов были одинаковыми, что (вместе с утверждением статического размера) гарантирует правильность.

На заре разработки компиляторов C ++ были примеры, когда компилятор сначала изменял ключевые слова struct с помощью class, а затем компилировал.Так много о сходстве.

Различия связаны с наследованием классов и, особенно, виртуальных функций.Если класс содержит виртуальные функции, то в начале его макета должен быть указатель на дескриптор типа.Кроме того, если класс B наследуется от класса A, то на первом месте стоит макет класса A, за которым следует собственный макет класса B.

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

Вот статья, которая показывает, что не так уж много нужно сделать, чтобы перейти от структур C к классам C ++: Урок 1 - От Структуры к классу

И вот статья, в которой объясняется, как таблица виртуальных функций вводится в классы, которые имеют виртуальные функции: Урок 4 - Полиморфизм

Классы & amp; структуры в C ++ эквивалентны, за исключением того, что все члены структуры являются открытыми по умолчанию (члены класса являются закрытыми по умолчанию). Это гарантирует, что компиляция устаревшего кода C в компиляторе C ++ будет работать как положено.

Ничто не мешает вам использовать все необычные функции C ++ в структуре:

struct ReallyAClass
{
    ReallyAClass();
    virtual !ReallAClass();

    /// etc etc etc
};

Почему бы явно не назначить членов класса структуре, когда вы хотите передать данные в C? Таким образом, вы знаете, что ваш код будет работать где угодно.

Вы, вероятно, просто выводите класс из структуры, публично или приватно. Затем приведение будет правильно разрешено в коде C ++.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top