Как макет памяти класса и структуры

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

Теперь я программирую на С++, и вместо этого я использую класс. Я в основном хочу добиться того же, но мне также нужны методы get/set, а также, возможно, другие методы (я также хочу попробовать сделать это в стиле С++, а Maye узнать что-то новое).

Есть ли гарантия, например. что общедоступные переменные будут первыми в памяти, а затем частной переменной?

Ответ 1

Есть ли гарантия, например. что общедоступные переменные будут первыми в а затем частную переменную?

Нет, такая гарантия не - С++ 11 standard, [class.mem]/14:

Нестационарные члены данных (неединичного) класса с одинаковым доступом control (раздел 11) распределяются так, что более поздние члены имеют более высокий адресов внутри объекта класса. Порядок распределения нестатических члены данных с различным контролем доступа не определены (11).

Итак,

struct A
{
    int i, j;
    std::string str;

private:

    float f;

protected:

    double d;
};

Гарантируется, что для данного объекта типа A,

  • i имеет меньший адрес, чем j и
  • j имеет меньший адрес, чем str

Обратите внимание, что ключи класса struct и class не имеют никакого отношения к компоновке: их единственная разница - права доступа, которые существуют только во время компиляции.


Он говорит только о порядке, но не о том, что первая переменная действительно начинается на "первом адресе"? Давайте предположим класс без наследования.

Да, но только для классов стандартного макета. Существует ряд требований, которые класс должен удовлетворять классу стандартного макета, одним из которых является то, что все члены имеют один и тот же контроль доступа.
Цитирование С++ 14 (то же самое относится к С++ 11, но формулировка более косвенная), [class.mem]/19:

Если объект класса стандартного макета имеет нестатические элементы данных, его адрес совпадает с адресом его первых нестатических данных член. В противном случае его адрес совпадает с адресом его первого base classsubobject (если есть). [Примечание: возможно, неназванное заполнение в рамках объекта структуры стандартного макета, но не в его начале, по мере необходимости для достижения соответствующего выравнивания. - конечная нота]

[класс]/7:

Класс стандартного макета - это класс, который:

  • не имеет нестатических членов данных типа нестандартного макета класса (или массива таких типов) или ссылки,
  • не имеет виртуальных функций (10.3) и нет виртуальных базовых классов (10.1),
  • имеет тот же контроль доступа (раздел 11) для всех нестатических членов данных,
  • не имеет базовых классов нестандартной компоновки,
  • либо не имеет нестатических членов данных в самом производном классе и не более одного базового класса с нестатическими членами данных, либо не имеет базы классы с нестатическими элементами данных и
  • не имеет базовых классов того же типа, что и первый нестатический член данных. 110

110) Это гарантирует, что два подобъекта, которые имеют один и тот же тип класса и которые принадлежат одному и тому же самому производному объекту, не являются выделенных по тому же адресу (5.10).

Ответ 2

Первое: class и struct в С++ - это почти то же самое - единственное отличие состоит в том, что все члены перед первым спецификатором доступа в class считаются закрытыми, а в struct они являются общедоступными.

Есть ли гарантия, например. что общедоступные переменные будут первыми в памяти, а затем частной переменной?

Нет такой гарантии. Когда нет наследования, память будет выделена членам класса в том порядке, в котором вы объявляете их в пределах одной группы доступа. Компилятор должен решить, следует ли размещать переменные public member перед частными/защищенными или наоборот. Подобно C, С++ может добавлять дополнение между членами класса.

Наследование делает вещи более сложными, потому что члены данных базового класса также должны быть помещены в производный класс. Кроме того, существует виртуальное наследование и множественное наследование со сложными правилами.

В основном я хочу добиться того же [layout], но мне также нужны методы get/set, а также, возможно, другие методы.

Если вы сделаете все члены данных своего класса частными и добавите функции-члены доступа (что то, что С++ вызывает "методы" с других языков), вы достигнете этого эффекта.