Posted onIn标准解读
,
C++标准Views: Symbols count in article: 2.6kReading time ≈7 mins.
Many C++ books do not clearly state the difference between declaration and definition, or they only mention the need to support separate compilation, indicating that using the extern specifier is a declaration, while without it is a definition. In fact, I think the C++ standard describes the difference between declaration and definition more clearly.
In section 2.2.2 of “C++ Primer 5th,” it mentions the relationship between variable declarations and definitions:
To support separate compilation, the C++ language distinguishes between declarations and definitions. A declaration makes the name known to the program; a file must include the declaration of a name to use a name defined elsewhere. A definition is responsible for creating the entity associated with the name. To declare a variable without defining it, add the extern keyword before the variable name and do not explicitly initialize the variable.
1 2
externint i; // declares i rather than defines i int j; // declares and defines j
Any declaration that includes an explicit initialization becomes a definition. We can give a variable marked with the extern keyword an initial value, but doing so negates the effect of extern. An extern statement containing an initializer is no longer a declaration but a definition.
1
externdouble pi=3.14159; // definition
The above is the description of the relationship between variable declarations and definitions in C++ Primer. I think the description in the C++ standard is more comprehensive:
A declaration is a definition unless:
it declares a function without specifying the function’s body (8.4),
it contains the extern specifier (7.1.1) or a linkage-specification (7.5) and neither an initializer nor a function-body,
it declares a static data member in a class definition (9.2, 9.4),
it is a class name declaration (9.1),
it is an opaque-enum-declaration (7.2),
it is a template-parameter (14.1),
it is a parameter-declaration (8.3.5) in a function declarator that is not the declarator of a function-definition, or
it is a typedef declaration (7.1.3),
an alias-declaration (7.1.3),
a using-declaration (7.3.3),
a static_assert-declaration (Clause 7),
an attribute-declaration (Clause 7),
an empty-declaration (Clause 7), or
a using-directive (7.3.4).
Let me briefly translate this. A declaration is a definition unless:
it declares a function but does not specify the function body.
1
intfunc(); // declaration
it contains an extern specifier or a linkage-specification (e.g., extern “C”) and has neither an initializer nor a function body.
1 2
externint x; extern"c"voidfunc();
it declares a static data member within a class definition.
1 2 3 4 5 6 7
structA{ A(){}; staticint x; // declaration staticconstint y=11; // define // notice: non-const static data member must be initialized out of line }; int A::x=12; // define
it is a class name declaration.
1
structA;
it is an opaque-enum-declaration.
1
enumA:int;
it is a template parameter.
1
template<typename T> T f(T); // T is a declaration
it is a parameter declaration in a function declaration.
1
intfunc(int x);
it is a typedef declaration.
1
typedefint INT;
it is an alias declaration.
1
using INT=int;
it is a using declaration.
1 2 3 4 5
namespace A{ typedefint INT; }
using A::INT;
it is a static_assert declaration.
1
static_assert(foo());
it is an attribute declaration.
1
[[noreturn]] voidfunv();
it is an empty declaration.
1 2
// empty-declaration: ;
it is a using directive.
1
usingnamespace std;
In the above cases, declarations are not definitions. In simple terms, a “declaration” provides name and parameter prototypes, while a “definition” provides storage allocation and the corresponding implementation. Oh, I just realized that cppreference already has this: Define and ODR.
The article is finished. If you have any questions, please comment and communicate.