View in Telegram
Константная инициализация. Ч1 Это первый шаг, который пытается выполнить компилятор, когда пробует инициализировать переменную. Для него требуется, чтобы инициализатор был константным выражением. То есть его можно было бы вычислить во время компиляции. И не путать с обычным const! Позже покажу почему. Также гарантируется, что эта инициализация происходит до любой другой инициализации статиков. На практике же компиляторы вообще сразу в бинарь помещают предвычисленное значение объекта и во время выполнения с ним уже ничего не нужно делать. Пример:
constexpr double constexpr_var{1.0};
double const_intialized_var1{constexpr_var};
const double const_var{const_intialized_var1};
double const_intialized_var2{3.0};
С переменной constexpr_var все хорошо, константа присваивается константному выражению и инициализируется эта переменная первой. Далее устанавливается значение для const_intialized_var1. Несмотря на то, что эта переменная не константа, ее инициализатор - константное выражение, а этого достаточно для выполнения константной инициализации. Интересно, что дальше устанавливается значение переменной const_intialized_var2, а не const_var. Хоть const_var и константа, ее инициализатор не является константным выражением! Все потому, что у переменной const_intialized_var1 нет пометки const(constexpr), а значит, хоть она и проинициализирована константой, сама таковой не является. И const_var будет инициализироваться последней уже в рантайме. Точнее немного не так. Она будет проиниализирована последней, но аж 2 раза! Первый раз - zero-инициализацией на этапе компиляции, второй раз - динамической в рантайме. Чтобы не пустословить по чем зря, покажу вырезки из ассембера, которые подкрепляют мои слова. Вот чего нашел:
  .section  __DATA,__data
  .globl  _const_intialized_var1          ## @const_intialized_var1
  .p2align  3, 0x0
_const_intialized_var1:
  .quad  0x3ff0000000000000              ## double 1

  .globl  _const_intialized_var2          ## @const_intialized_var2
  .p2align  3, 0x0
_const_intialized_var2:
  .quad  0x4008000000000000              ## double 3

  .section  __TEXT,__const
  .p2align  3, 0x0                          ## @_ZL13constexpr_var
__ZL13constexpr_var:
  .quad  0x3ff0000000000000              ## double 1

.zerofill __DATA,__bss,__ZL9const_var,8,3 ## @_ZL9const_var
  .section  __DATA,__mod_init_func,mod_init_funcs
  .p2align  3, 0x0
  .quad  __GLOBAL__sub_I_main.cpp
constexpr_var инициализируется в текстовой секции. Не смотрите, что эта секция расположена в середине, стандарт гарантирует, что ее инициализация произойдет первой(в ином случае const_intialized_var1 досталась бы фига). Дальше мы переходим к data секции, в которой подряд инициализируются const_intialized_var1 и _const_intialized_var2. И после всего этого в секции .zerofill у нас заполняется нулями const_var. И в последнюю очередь, уже в рантайме, динамически ини
циализируется const_var.

  
  .section  __TEXT,__StaticInit,regular,pure_instructions
  .p2align  4, 0x90                         ## -- Begin function __cxx_global_var_init
___cxx_global_var_init:                 ## @__cxx_global_var_init
  .cfi_startproc
## %bb.0:
  pushq  %rbp
  .cfi_def_cfa_offset 16
  .cfi_offset %rbp, -16
  movq  %rsp, %rbp
  .cfi_def_cfa_register %rbp
  movsd  _const_intialized_var1(%rip), %xmm0 ## xmm0 = mem[0],zero
  movsd  %xmm0, __ZL9const_var(%rip)
  popq  %rbp
  retq
  .cfi_endproc
Это рантаймовая рутина, которая запускается перед вызовом main() и инициализирует const_var. Тут можно довольно простую аналогию провести. Константная инициализаци выполняется для тех объектов, которые можно пометить constexpr, и, не учитывая весь остальной код, компиляция после этого успешно завершится. Define order of your life. Stay cool. #cppcore #compiler
Love Center - Dating, Friends & Matches, NY, LA, Dubai, Global
Love Center - Dating, Friends & Matches, NY, LA, Dubai, Global
Find friends or serious relationships easily