C vs C ++ Статическая инициализация объектов

0

У меня вопрос об инициализации довольно больших наборов статических данных.

Ниже приведены три приведенных ниже примера инициализации наборов статических данных. Я хотел бы понять значения времени загрузки программы и объема памяти для методов, показанных ниже. Я действительно не знаю, как оценивать это самостоятельно в данный момент. Моя среда сборки все еще находится на рабочем столе с использованием Visual Studio, однако встроенные цели будут скомпилированы для VxWorks с использованием GCC.

Традиционно я использовал базовые C-структуры для такого рода вещей, хотя есть веские основания переместить эти данные в классы C++, продвигаясь вперед. Динамическое распределение памяти не рекомендуется во встроенном приложении и избегается там, где это возможно.

Насколько я знаю, единственный способ инициализировать класс C++ - через его конструктор, показанный ниже в методе 2. Мне интересно, как это сравнивается с методом 1. Есть ли заметные дополнительные накладные расходы с точки зрения ПЗУ (площадь программы), RAM (Memory Footprint) или время загрузки программы? Мне кажется, что компилятор может оптимизировать довольно тривиальный конструктор, но я не уверен, что это обычное поведение.

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

/* C-Style Struct Storage */
typedef struct{
    int a;
    int b;
}DATA_C;

/* CPP Style Class Storage */
class DATA_CPP{
public:
    int a;
    int b;
    DATA_CPP(int,int);
};
DATA_CPP::DATA_CPP(int aIn, int bIn){
    a = aIn;
    b = bIn;
}

/* METHOD 1: Direct C-Style Static Initialization */
DATA_C MyCData[5] = { {1,2},
                      {3,4},
                      {5,6},
                      {7,8},
                      {9,10}
                    };

/* METHOD 2: Direct CPP-Style Initialization */ 
DATA_CPP MyCppData[5] = { DATA_CPP(1,2),
                          DATA_CPP(3,4),
                          DATA_CPP(5,6),
                          DATA_CPP(7,8),
                          DATA_CPP(9,10),
                         };

/* METHOD 3: Cast C-Struct to CPP class */
DATA_CPP* pMyCppData2 = (DATA_CPP*) MyCData;
  • 0
    Честно говоря, я не вижу, чтобы это сильно повлияло, если вообще что-то произошло. Известно, что C быстрее, но не очень в наши дни с современными компиляторами.
Теги:
arrays
initialization

2 ответа

1

Я сделал несколько исследований в этом, думал, что опубликую результаты. Здесь я использовал Visual Studio 2008 во всех случаях.

Здесь представлен вид дизассемблирования кода из Visual Studio в режиме отладки:

/* METHOD 1: Direct C-Style Static Initialization */
DATA_C MyCData[5] = { {1,2},
                      {3,4},
                      {5,6},
                      {7,8},
                      {9,10},
                    };

/* METHOD 2: Direct CPP-Style Initialization */ 
DATA_CPP MyCppData[5] = { DATA_CPP(1,2),
010345C0  push        ebp  
010345C1  mov         ebp,esp 
010345C3  sub         esp,0C0h 
010345C9  push        ebx  
010345CA  push        esi  
010345CB  push        edi  
010345CC  lea         edi,[ebp-0C0h] 
010345D2  mov         ecx,30h 
010345D7  mov         eax,0CCCCCCCCh 
010345DC  rep stos    dword ptr es:[edi] 
010345DE  push        2    
010345E0  push        1    
010345E2  mov         ecx,offset MyCppData (1038184h) 
010345E7  call        DATA_CPP::DATA_CPP (103119Ah) 
                          DATA_CPP(3,4),
010345EC  push        4    
010345EE  push        3    
010345F0  mov         ecx,offset MyCppData+8 (103818Ch) 
010345F5  call        DATA_CPP::DATA_CPP (103119Ah) 
                          DATA_CPP(5,6),
010345FA  push        6    
010345FC  push        5    
010345FE  mov         ecx,offset MyCppData+10h (1038194h) 
01034603  call        DATA_CPP::DATA_CPP (103119Ah) 
                          DATA_CPP(7,8),
01034608  push        8    
0103460A  push        7    
0103460C  mov         ecx,offset MyCppData+18h (103819Ch) 
01034611  call        DATA_CPP::DATA_CPP (103119Ah) 
                          DATA_CPP(9,10),
01034616  push        0Ah  
01034618  push        9    
0103461A  mov         ecx,offset MyCppData+20h (10381A4h) 
0103461F  call        DATA_CPP::DATA_CPP (103119Ah) 
                         };
01034624  pop         edi  
01034625  pop         esi  
01034626  pop         ebx  
01034627  add         esp,0C0h 
0103462D  cmp         ebp,esp 
0103462F  call        @ILT+325(__RTC_CheckEsp) (103114Ah) 
01034634  mov         esp,ebp 
01034636  pop         ebp  

Интересно отметить, что есть определенная часть накладных расходов на использование памяти программы и время загрузки, по крайней мере, в не оптимизированном режиме отладки. Обратите внимание, что метод 1 имеет нулевые инструкции по сборке, а метод два имеет около 44 инструкций.

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

?MyCData@@3PAUDATA_C@@A DD 01H              ; MyCData
    DD  02H
    DD  03H
    DD  04H
    DD  05H
    DD  06H
    DD  07H
    DD  08H
    DD  09H
    DD  0aH

?MyCppData@@3PAVDATA_CPP@@A DD 01H          ; MyCppData
    DD  02H
    DD  03H
    DD  04H
    DD  05H
    DD  06H
    DD  07H
    DD  08H
    DD  09H
    DD  0aH
END

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

Я думал, что попробую что-нибудь еще. Я сменил конструктор на:

DATA_CPP::DATA_CPP(int aIn, int bIn){
    a = aIn + bIn;
    b = bIn;
}

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

?MyCppData@@3PAVDATA_CPP@@A DD 03H          ; MyCppData
    DD  02H
    DD  07H
    DD  04H
    DD  0bH
    DD  06H
    DD  0fH
    DD  08H
    DD  013H
    DD  0aH
END

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

Я думал, что попробую что-то еще немного, оперирую глобальную переменную в конструкторе:

int globalvar;
DATA_CPP::DATA_CPP(int aIn, int bIn){
    a = aIn + globalvar;
    globalvar += a;
    b = bIn;
}

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

    ??__EMyCppData@@YAXXZ PROC              ; 'dynamic initializer for 'MyCppData'', COMDAT

; 35   : DATA_CPP MyCppData[5] = { DATA_CPP(1,2),

  00000 a1 00 00 00 00   mov     eax, DWORD PTR ?globalvar@@3HA ; globalvar
  00005 8d 48 01     lea     ecx, DWORD PTR [eax+1]
  00008 03 c1        add     eax, ecx
  0000a 89 0d 00 00 00
    00       mov     DWORD PTR ?MyCppData@@3PAVDATA_CPP@@A, ecx

; 36   :                           DATA_CPP(3,4),

  00010 8d 48 03     lea     ecx, DWORD PTR [eax+3]
  00013 03 c1        add     eax, ecx
  00015 89 0d 08 00 00
    00       mov     DWORD PTR ?MyCppData@@3PAVDATA_CPP@@A+8, ecx

; 37   :                           DATA_CPP(5,6),

  0001b 8d 48 05     lea     ecx, DWORD PTR [eax+5]
  0001e 03 c1        add     eax, ecx
  00020 89 0d 10 00 00
    00       mov     DWORD PTR ?MyCppData@@3PAVDATA_CPP@@A+16, ecx

; 38   :                           DATA_CPP(7,8),

  00026 8d 48 07     lea     ecx, DWORD PTR [eax+7]
  00029 03 c1        add     eax, ecx
  0002b 89 0d 18 00 00
    00       mov     DWORD PTR ?MyCppData@@3PAVDATA_CPP@@A+24, ecx

; 39   :                           DATA_CPP(9,10),

  00031 8d 48 09     lea     ecx, DWORD PTR [eax+9]
  00034 03 c1        add     eax, ecx
  00036 89 0d 20 00 00
    00       mov     DWORD PTR ?MyCppData@@3PAVDATA_CPP@@A+32, ecx
  0003c a3 00 00 00 00   mov     DWORD PTR ?globalvar@@3HA, eax ; globalvar

; 40   :                          };

  00041 c3       ret     0
??__EMyCppData@@YAXXZ ENDP              ; 'dynamic initializer for 'MyCppData''

FYI, я нашел эту страницу полезной при настройке visual studio для сборки сборки: Как получить вывод ассемблера из файла C в VS2005

  • 0
    Вы действительно должны использовать списки инициализаторов в своих конструкторах.
1

В С++ 11 вы можете написать следующее:

DATA_CPP obj = {1,2}; //Or simply : DATA_CPP obj {1,2}; i.e omit '='

вместо

DATA_CPP obj(1,2);

Расширяя это, вы можете написать:

DATA_CPP MyCppData[5] = { {1,2},
                          {3,4},
                          {5,6},
                          {7,8},
                          {9,10},
                         };

вместо этого:

DATA_CPP MyCppData[5] = { DATA_CPP(1,2),
                          DATA_CPP(3,4),
                          DATA_CPP(5,6),
                          DATA_CPP(7,8),
                          DATA_CPP(9,10),
                         };

Читайте об унифицированной инициализации.

  • 0
    Это все еще вызывает те же самые конструкторы, все же.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню