указатель на структуру или класс против указателя на первое поле

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

#include <iostream>

struct testingPointers
{
    int i;
    float f;
    double d;
} test;

int main()
{
   std::cout << &test << 'n' << &(test.i) << 'n' << 
            &(test.f) << 'n' << &(test.d);
}

и выход:

0x681110
0x681110
0x681114
0x681118

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

меня смущает потому что значение первого указателя--расположение памяти test--то же самое, что и у второго (первое поле test). Означает ли это, что объекты не имеют реального уникального адреса памяти и что указатель на структуру или класс просто указывает на его первое поле? Если да, то как сделать такие утверждения, как

a.b
a->b
a.b()

иметь смысл, если a на самом деле это только его первое поле, и поэтому не имеет никаких полей или методов?

4 ответов


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


адрес объекта всегда должен быть адресом первого нестатического элемента внутри этого объекта. Цитирование из стандарта (C++11-9.2-20):

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

требования к стандартные-макета упомянуты здесь: StandardLayoutType.

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

class X
{
public:
    int x;
};

class Y
{
public:
    X x;
    int y;
};

Y yobj;

стандартная, &yobj == &yobj.x == &yobj.x.x.


просто чтобы прояснить путаницу:

1).значение первого указателя-расположение памяти теста-такое же, как и у второго (первое поле теста).
Адрес Struct и его первое поле должны быть одинаковыми, так как struct-это не что иное, как совокупность его полей.

enter image description here

вы можете также рассмотреть дело массивов для дальнейшего упрощения понимания, в котором адрес массива очевидно, что он равен первому элементу (полю) массива.

2).Означает ли это, что объекты не имеют реального уникального адреса памяти и что указатель на структуру или класс просто указывает на его первое поле?
Я думаю, вы путаете его с JAVA, где объект всегда выделяется в куче. В C++ struct / class всегда выделяется в стеке, если это не динамическое выделение памяти (с использованием оператора "new"), где объект выделяется в куче и переменная указателя (в стеке) будет указывать на этот объект в куче. Поэтому в первом случае переменная struct всегда будет иметь тот же адрес, что и ее первый элемент (поле).

надеюсь, это поможет.


структура в памяти состоит не более чем из ее полей, связанных вместе. Перед структурой и/или между полями может быть заполнение, основанное на потребностях выравнивания, но обычно нет никаких дополнительных "вещей" перед первым полем. Таким образом, первое поле и сама структура имеют один и тот же адрес.

помните, что в C, существует только во время компиляции.