Значение обоих ускользает от меня.
c
declaration
terminology
definition
c++-faq
Maciek
источник
источник
Ответы:
Декларация вводит идентификатор и описывает его тип, будь то тип, объект или функция. Объявление - это то, что нужно компилятору для принятия ссылок на этот идентификатор. Это декларации:
Определение фактически инстанцирует / реализует этот идентификатор. Это то, что нужно компоновщику , чтобы связать ссылки с этими объектами. Это определения, соответствующие вышеуказанным декларациям:
Определение может быть использовано вместо объявления.
Идентификатор может быть объявлен так часто, как вы хотите. Таким образом, в C и C ++ допустимо следующее:
Однако это должно быть определено ровно один раз. Если вы забыли определить что-то, что было объявлено и где-то указано, то компоновщик не знает, на что ссылается ссылка, и жалуется на отсутствующие символы. Если вы определяете что-то более одного раза, то компоновщик не знает, на какое из определений ссылаться ссылки, и жалуется на дублированные символы.
Поскольку дебаты , что класс декларации против класса определения в C ++ продолжает придумывать (в ответах и комментариях на другие вопросы), я вставить цитату из C ++ стандарт.
В 3.1 / 2 C ++ 03 говорит:
3.1 / 3 затем приводит несколько примеров. Среди них:
Подводя итог: стандарт C ++ считает ,
struct x;
чтобы быть декларацией и определением . (Другими словами, «предварительное объявление» является неправильным , поскольку в C ++ нет других форм объявлений классов.)struct x {};
Спасибо Литбу (Йоханнесу Шаубу), который раскопал настоящую главу и стих в одном из своих ответов.
источник
extern int i
это объявление, так как оно просто вводит / указываетi
. Вы можете иметь столько,extern int i
сколько хотите в каждом модуле компиляции.int i
Однако это определение. Он обозначает пространство для целого числа, которое должно быть в этом модуле перевода, и рекомендует компоновщику связать все ссылкиi
с этим объектом. Если у вас есть более или менее одно из этих определений, компоновщик будет жаловаться.int i;
в файловой / глобальной области видимости или в области функций - это определение как в C, так и в C ++. В C, потому что он выделяет память, и в C ++, потому что у него нет спецификатора extern или спецификации связи. Это равносильно тому, что говорит sbi: в обоих случаях это объявление указывает объект, с которым должны быть связаны все ссылки на «i» в этой области.struct A { double f(int, double); double f(int, double); };
недействительный, конечно. Это разрешено в другом месте, хотя. Есть несколько мест , где вы можете объявить вещи, но не определяет, тоже:void f() { void g(); }
действительно, но не следующее:void f() { void g() { } };
. Что такое определение и какое объявление имеет тонкие правила, когда дело доходит до шаблонов - будьте осторожны! +1 за хороший ответ.Из стандартного раздела 3.1 C ++:
Следующий абзац гласит (выделение мое), что объявление является определением, если ...
... он объявляет функцию без указания тела функции:
... он объявляет статический член в определении класса:
... он объявляет имя класса:
... содержит
extern
ключевое слово без инициализатора или тела функции:... или является
typedef
илиusing
заявлением.Теперь по большой причине, почему важно понимать разницу между декларацией и определением: Правило единого определения . Из раздела 3.2.1 стандарта C ++:
источник
struct x {static int b = 3; };
?b
не объявленоconst
. См. Stackoverflow.com/a/3536513/1858225 и daniweb.com/software-development/cpp/threads/140739/... .Декларация: «Где-то существует фу».
Определение: "... и вот оно!"
источник
В C ++ есть интересные крайние случаи (некоторые из них тоже в C). Рассматривать
Это может быть определение или объявление, в зависимости от типа
T
:В C ++ при использовании шаблонов есть еще один крайний случай.
Последнее заявление не было определением. Это объявление явной специализации статического члена
X<bool>
. Он говорит компилятору: «Если речь идет оX<bool>::member
создании экземпляра , не создавайте экземпляр определения элемента из основного шаблона, а используйте определение, найденное в другом месте». Чтобы сделать это определение, вы должны предоставить инициализатористочник
декларация
Определение
источник
class foo {};
является класс определение , не так ли?Из стандарта С99 6,7 (5):
Объявление определяет интерпретацию и атрибуты набора идентификаторов. Определение идентификатора является декларацией для этого идентификатора , что:
Из стандарта C ++, 3.1 (2):
Декларация является определением если только оно не объявляет функцию без указания тела функции, оно содержит спецификатор extern или спецификацию связи и не является ни инициализатором, ни телом функции, оно объявляет член статических данных в объявлении класса, это объявление имени класса, или это объявление typedef, объявление-использование или директива-использование.
Тогда есть несколько примеров.
Интересно (или нет, но я немного удивлен этим),
typedef int myint;
это определение в C99, но только объявление в C ++.источник
typedef
, разве это не означает, что это можно повторить в C ++, но не в C99?С wiki.answers.com:
Термин объявление означает (на языке C), что вы сообщаете компилятору о типе, размере и, в случае объявления функции, типе и размере ее параметров любой переменной, или определенного пользователем типа или функции в вашей программе. В случае объявления в памяти не зарезервировано ни одной переменной. Однако компилятор знает, сколько места нужно зарезервировать в случае создания переменной этого типа.
например, ниже приведены все объявления:
Определение, с другой стороны, означает, что в дополнение ко всем вещам, которые делает объявление, пространство также резервируется в памяти. Вы можете сказать «ОПРЕДЕЛЕНИЕ = ДЕКЛАРАЦИЯ + ПРОБЛЕМА ПРОСТРАНСТВА». Ниже приведены примеры определения:
см. ответы .
источник
struct foo {};
это определение , а не декларация. Декларация оfoo
будетstruct foo;
. Исходя из этого, компилятор не знает, сколько места зарезервировать дляfoo
объектов.struct foo;
это объявление, но оно не сообщает компилятору размер foo. Я бы добавил, чтоstruct _tagExample { int a; int b; };
это определение. Поэтому в этом контексте вводить в заблуждение называть это декларацией. Конечно, это одно, поскольку все определения являются декларациями, но вы, похоже, предполагаете, что это не определение. Это определение _tagExample.C ++ 11 Обновление
Поскольку я не вижу ответа, относящегося к C ++ 11, вот один.
Объявление является определением, если оно не объявляет / n:
enum X : int;
template<typename T> class MyArray;
int add(int x, int y);
using IntVector = std::vector<int>;
static_assert(sizeof(int) == 4, "Yikes!")
;
Дополнительные пункты, унаследованные от C ++ 03 приведенным выше списком:
int add(int x, int y);
extern int a;
илиextern "C" { ... };
class C { static int x; };
struct Point;
typedef int Int;
using std::cout;
using namespace NS;
Шаблон-объявление - это объявление. Объявление шаблона также является определением, если его объявление определяет функцию, класс или статический член данных.
Примеры из стандарта, которые различают декларацию и определение, которые я нашел полезными для понимания нюансов между ними:
источник
Определение:
Определение связывает переменную с типом и выделяет память, тогда как объявление просто указывает тип, но не выделяет память. Объявление более полезно, когда вы хотите обратиться к переменной перед определением.
* Не путайте определение с инициализацией. Оба отличаются, инициализация дает значение переменной. Смотрите приведенный выше пример.
Ниже приведены некоторые примеры определения.
Теперь объявление функции:
Обратите внимание на точку с запятой в конце функции, поэтому она говорит, что это всего лишь объявление. Компилятор знает, что где-то в программе эта функция будет определена с этим прототипом. Теперь, если компилятор получает вызов функции что-то вроде этого
Компилятор выдаст ошибку о том, что такой функции нет. Потому что у него нет прототипа для этой функции.
Обратите внимание на разницу между двумя программами.
Программа 1
При этом функция печати также объявляется и определяется. Поскольку вызов функции идет после определения. Теперь посмотрим на следующую программу.
Программа 2
Это важно, потому что вызов функции предшествует определению, поэтому компилятор должен знать, есть ли такая функция. Итак, мы объявляем функцию, которая сообщит компилятору.
Определение:
Эта часть определения функции называется Определение. Он говорит, что делать внутри функции.
источник
int a; //declaration; a=10; //definition
Это совершенно неправильно. Когда речь идет об объектах длительности автоматического хранения (объекты, объявленные внутри определения функции, которые не объявлены с другим спецификатором класса хранения, например extern), это всегда определения.определение означает фактическую написанную функцию, а объявление означает простую функцию объявления, например, для
а также
это определение функции myfunction
источник
Практическое правило:
Декларация сообщает компилятор , как интерпретировать данные переменные в памяти. Это необходимо для каждого доступа.
Определение оставляет память , чтобы сделать переменную существующие. Это должно произойти ровно один раз перед первым доступом.
источник
Чтобы понять существительные, давайте сначала сосредоточимся на глаголах.
объявить - объявить официально; Proclaim
определить - показать или описать (кого-то или что-то) ясно и полностью
Итак, когда вы заявляете что-то, вы просто говорите, что это такое .
Эта строка объявляет вызываемую функцию C,
sum
которая принимает два аргумента типаint
и возвращаетint
. Тем не менее, вы не можете использовать его пока.Когда вы предоставляете, как это на самом деле работает , это определение.
источник
Чтобы понять разницу между объявлением и определением, нам нужно увидеть код сборки:
и это только определение:
Как видите, ничего не меняется.
Объявление отличается от определения, потому что оно дает информацию, используемую только компилятором. Например, uint8_t говорит компилятору использовать функцию asm movb.
Видеть, что:
У объявления нет эквивалентной инструкции, потому что это не то, что должно быть выполнено.
Кроме того, объявление сообщает компилятору область действия переменной.
Мы можем сказать, что объявление - это информация, используемая компилятором для установления правильного использования переменной и того, как долго некоторая память принадлежит определенной переменной.
источник
Не могли бы вы в самых общих терминах заявить, что объявление - это идентификатор, в котором не выделяется хранилище, а определение фактически выделяет хранилище из объявленного идентификатора?
Одна интересная мысль - шаблон не может выделять память, пока класс или функция не связаны с информацией о типе. Так является ли идентификатор шаблона декларацией или определением? Это должно быть объявление, поскольку хранилище не выделено, а вы просто «создаете прототип» класса или функции шаблона.
источник
template<class T> struct foo;
это объявление шаблона , как и этоtemplate<class T> void f();
. Определения шаблонов отражают определения классов / функций таким же образом. (Обратите внимание, что имя шаблона не является именем типа или функции . Это можно увидеть в одном месте, когда вы не можете передать шаблон в качестве параметра типа другого шаблона. Если вы хотите передавать шаблоны вместо типов, вам нужны параметры шаблона шаблона. )Найти похожие ответы здесь: Технические вопросы интервью в C .
Декларация предоставляет имя к программе; определение обеспечивает однозначное описание объекта (например , типа, экземпляр, и функцию) в рамках программы. Объявления могут повторяться в заданной области, это вводит имя в данной области.
Объявление является определением, если:
Определение является декларацией, если:
источник
Это будет звучать по-настоящему глупо, но это лучший способ, которым я смог держать слова прямо в голове:
Декларация: фото Томаса Джефферсона, выступающего с речью ... "Я НАСТОЯЩИМ ОБЪЯВЛЯЮ, ЧТО ЭТО ФУО СУЩЕСТВУЕТ В ЭТОМ КОДЕКСЕ ИСТОЧНИКА !!!"
Определение: представьте себе словарь, вы ищете Foo и что это на самом деле означает.
источник
Объявление представляет имя символа для компилятора. Определение - это объявление, которое выделяет место для символа.
источник
Согласно руководству по библиотеке GNU C ( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )
источник
Концепция объявления и определения образует ловушку, когда вы используете класс внешнего хранилища, потому что ваше определение будет находиться в каком-то другом месте, и вы объявляете переменную в своем локальном кодовом файле (странице). Одно из различий между C и C ++ состоит в том, что в C вы объявления обычно делаются в начале функции или кодовой страницы. В С ++ это не так. Вы можете заявить в любом месте по вашему выбору.
источник
Мой любимый пример - "int Num = 5", здесь ваша переменная 1. определена как int 2. объявлена как Num и 3. создана со значением пять. Мы
Класс или структура позволяет вам изменить способ определения объектов при их последующем использовании. Например
Когда мы учимся программировать, эти два термина часто путаются, потому что мы часто делаем оба одновременно.
источник
Этапы исполняемого поколения:
На этапе 2 (переводчик / компилятор) операторы объявления в нашем коде сообщают компилятору, что эти вещи мы будем использовать в будущем, и вы сможете найти определение позже, что означает:
и (3) стадия (линкер) нуждается в определении, чтобы связать вещи
источник
Есть несколько очень четких определений, разбросанных по всему K & R (2-е издание); это помогает поместить их в одно место и читать их как одно:
источник
Объявление означает присвоение имени и типа переменной (в случае объявления переменной), например:
или дать имя, тип возвращаемого значения и тип параметра (ов) для функции без тела (в случае объявления функции), например:
тогда как определение означает присвоение значения переменной (в случае определения переменной), например:
или предоставление / добавление тела (функциональности) к функции называется определением функции, например:
многократное объявление и определение могут быть сделаны вместе как:
а также:
В вышеупомянутых случаях мы определяем и объявляем переменную
i
иfunction max()
.источник
int x;