2009-09-24 3 views
4

Если у меня есть список глобальных переменных, как это ...Хранение переменных в памяти

int a; 
char b; 
float c[10]; 
double d[3]; 

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

class test_type 
{ 
    int a; 
    char b; 
    float c[10]; 
    double d[3]; 
} 

гарантировано, что расположение всех переменных в памяти идентично. то есть «b» гарантированно хранится сразу после «a» как в списке глобальных таблиц, так и в списке классов?

EDIT: Я прошу, потому что я хотел, чтобы A) скопировал данные из одного в другое как «место работы» и B). Я хотел проверить любые различия между ними в качестве задания. Если ответ на главный вопрос «нет», то есть ли у кого-нибудь какие-либо предложения относительно того, как я обойду проблему, предпочтительно оставляя существующий код как можно более неизменным.

ответ

8

Нет. Я не думаю, что стандарт C++ гарантирует что-либо о макете памяти глобальных переменных.

+2

Это действительно что-то гарантирует. Сохраняется порядок последовательно объявленных элементов класса/структуры с одним и тем же спецификатором доступа. Тем не менее, может быть и некоторое дополнение. – sellibitze

+2

Да, но Йеспер сказал «глобальные переменные». – Skilldrick

+0

Правда. Я пропустил это, извините. – sellibitze

0

Распределение памяти зависит от компилятора. Таким образом, непрерывное распределение или идентичное распределение глобальных переменных и переменных класса не может быть гарантировано.

0

Нет, вы не можете положиться на это. Речь идет о компиляторе, как распределять память для переменных.

0

Нет, это не гарантировано. В зависимости от того, что вы хотели бы сделать, вы можете использовать операторы «указатель-член», чтобы убедиться, что вы знаете относительный адрес переменной-члена.

Так что в вашем классе:

class test_type 
{ 
    int a; 
    char b; 
    float c[10]; 
    double d[3]; 
} 

void* pa = &test_type::a; 
void* pb = &test_type::b; 
void* pc = &test_type::c; 
void* pd = &test_type::d; 

void main() 
{ 
    std::cout << "Relative address of member 'a' " << (int)pa << std::endl; 
    std::cout << "Relative address of member 'b' " << (int)pb << std::endl; 
    std::cout << "Relative address of member 'c' " << (int)pc << std::endl; 
    std::cout << "Relative address of member 'd' " << (int)pd << std::endl; 
} 

Насколько я знаю, она работает с MSVC и GCC, а также.

+2

Это потому, что порядок переменных, определенных внутри класса/структуры, безусловно, гарантирован. Это не глобальные переменные. – kdgregory

+0

Возможно, вы правы, но мое решение не означает никаких дополнительных операций и, как правило, говорит, что он не полагается на принцип, который может быть легко изменен при реализации. (Я не совсем уверен, как это влияет на проблемы выравнивания ...) – progician

+0

Ваше «решение» демонстрирует то, что, как известно, верно. Он не решает желаемую цель OP копировать глобальные переменные в структуру с одной операцией. – kdgregory

1

Стандарты C/C++ не требуют сохранения переменных в порядке их деклараций. Поэтому компиляторы могут хранить переменные в том порядке, в котором они хотят. Но гарантируется, что они будут инициализированы в порядке их объявления. Это справедливо как для глобальных переменных, так и для переменных класса.

Некоторые примечания по глобальным переменным: в блоке компиляции они будут инициализированы в указанном порядке, но этот gurantee не применяется через единиц компиляции.

0

Мик - для того, чтобы делать то, что вы хотите (копия/тест), вам просто нужно

  • добавить конструктор test_type класса, а также не-конструктор init_from_globals() (чей код копирует 4 значения по одному, массивы, скопированные в цикле или через memcopy).

  • Добавить «diff_from_globals) (» метод, который снова Diffs 4 членов индивидуально

Это немного менее эффективным/элегантнее, чем то, что вы хотели, насколько реализации, но завернутые в методе, в-элегантность полностью скрыта от остальной части кода:

6

Почему бы вам просто не использовать глобальный объект типа test_type вместо определения нескольких глобальных переменных?

class test_type 
{ 
    int a; 
    char b; 
    float c[10]; 
    double d[3]; 
}; 

test_type global; 

Теперь это кусок пирога, чтобы инициализировать новый объект test_type с копией «глобальной».

0

Я думаю, что людям не хватает точки. Всегда опасно предполагать любую компоновку, поскольку это может измениться с CPU на CPU, компилятор на компилятор и даже на степень оптимизации.

C++ генерирует функцию присваивания копии по умолчанию, как если бы вы написали это:

class test_type 
{ 
    int a; 
    char b; 
    float c[10]; 
    double d[3]; 
public: 
    test_type &operator=(const test_type &other) 
    { 
    // copy all of the members one by one. 
    } 
} 

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

+0

Итак? В этом случае неявно сгенерированный оператор присваивания не наносит вреда. – sellibitze

+0

Конечно нет. Я считаю хорошей практикой создавать классы, для которых оператор по умолчанию работает правильно. Например, я использую std :: string вместо char *. –