#cpp
В чём разница между определением, объявлением, реализацией и инициализацией?
Ответы
Ответ 1
Если совсем кратко: typedef int MyType; // объявление синонима типа extern int value; // объявление переменной int value; // объявление + определение посредством неявной инициализации int value2 = 0; // объявление + определение посредством явной инициализации значением 0 int func(); // объявление функции (прототип функции) int func(){ return 0; } // определение функции посредством реализации class SomeClass; // объявление класса class SomeClass // определение класса { static int field; }; // объявление static члена класса int SomeClass::field = 0; // определение static члена класса посредством инициализации значением 0 Явная и неявная инициализация переменных Если при определении переменной не происходит явного присвоения ей какого-либо значения (т.е. не происходит явной инициализации), то компилятор может проинициализировать её сам в соответствии со следующими правилами: переменные со статическим временем существования (глобальные, в пространствах имен и статические) инициализируются нулем автоматические переменные не инициализируются (т.е. имеют случайное значение той области стека, которую компилятор выделил под переменную) динаммические переменные не инициализируются (т.е. имеют случайное значение той области памяти, которая была выделена под объект в куче) Стоит заметить, что в большинстве реализаций в debug-версии под автоматические переменные область стека заполняется значениями 0xCCCCCCCC, а область heap (кучи) заполняется 0xCDCDCDCD, что может позволить при отладке выявлять использование неинициализированных переменных. Объявление и определение Стоит заметить, что объявлений может быть сколь угодно много, а определение лишь одно (за исключением inline функций, которые при этом не нарушают ODR).Ответ 2
Хоть вопрос и старый, но я вставлю свои 5 копеек. @StateItPrimitive утверждает, что объявлений может быть сколь угодно много, а определение лишь одно. Но ведь существуют weak-функции, которые могут иметь сколь угодно определений. Например, в этом случае: _weak int foo() { return 0; } int foo() { return 1; } скомпилируются обе функции, но линковщик выбросит "слабую". В этом случае: _weak int foo() { return 0; } _weak int foo() { return 1; } линковщик не сможет выбрать правильную функцию и выдаст ошибку. В этом случае: _weak int foo() { return 0; } всё в порядке, ошибок нет. Слабое связывание применяется, в основном, в низкоуровневом программировании при создании обработчиков прерываний. Обычно в библиотеках, работающих с ядром, создаются обработчики прерываний по умолчанию, и они определяются как weak. При этом программист может написать свой обработчик, который никак не будет конфликтовать с обработчиком по умолчанию. UPD. Насчет стандарта не знаю, не читал (всё-таки денег стоит), но в документации по gcc это есть. The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions which can be overridden in user code, though it can also be used with non-function declarations. Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker.
Комментариев нет:
Отправить комментарий