After reading the question, I know the differences between declaration and definition. So does it mean definition equals declaration plus initialization?
Declaration
Declaration, generally, refers to the introduction of a new name in the program. For example, you can declare a new function by describing it's "signature":
void xyz();
or declare an incomplete type:
class klass;
struct ztruct;
and last but not least, to declare an object:
int x;
It is described, in the C++ standard, at §3.1/1 as:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
Definition
A definition is a definition of a previously declared name (or it can be both definition and declaration). For example:
int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };
Specifically the C++ standard defines it, at §3.1/1, as:
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-specification25 (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).
Initialization
Initialization refers to the "assignment" of a value, at construction time. For a generic object of type T, it's often in the form:
T x = i;
but in C++ it can be:
T x(i);
or even:
T x {i};
with C++11.
Conclusion
So does it mean definition equals declaration plus initialization?
It depends. On what you are talking about. If you are talking about an object, for example:
int x;
This is a definition without initialization. The following, instead, is a definition with initialization:
int x = 0;
In certain context, it doesn't make sense to talk about "initialization", "definition" and "declaration". If you are talking about a function, for example, initialization does not mean much.
So, the answer is no: definition does not automatically mean declaration plus initialization.
Declaration says "this thing exists somewhere":
int foo(); // function
extern int bar; // variable
struct T
{
static int baz; // static member variable
};
Definition says "this thing exists here; make memory for it":
int foo() {} // function
int bar; // variable
int T::baz; // static member variable
Initialisation is optional at the point of definition for objects, and says "here is the initial value for this thing":
int bar = 0; // variable
int T::baz = 42; // static member variable
Sometimes it's possible at the point of declaration instead:
struct T
{
static int baz = 42;
};
…but that's getting into more complex features.
For C, at least, per C11 6.7.5:
A declaration specifies the interpretation and attributes of a set of
identifiers. A definition of an identifier is a declaration for that
identifier that:
for an object, causes storage to be reserved for that object;
for a function, includes the function body;
for an enumeration constant, is the (only) declaration of the identifier;
for a typedef name, is the first (or only) declaration of the identifier.
Per C11 6.7.9.8-10:
An initializer specifies the initial value stored in an object ... if
an object that has automatic storage is not initialized explicitly,
its value is indeterminate.
So, broadly speaking, a declaration introduces an identifier and provides information about it. For a variable, a definition is a declaration which allocates storage for that variable.
Initialization is the specification of the initial value to be stored in an object, which is not necessarily the same as the first time you explicitly assign a value to it. A variable has a value when you define it, whether or not you explicitly give it a value. If you don't explicitly give it a value, and the variable has automatic storage, it will have an initial value, but that value will be indeterminate. If it has static storage, it will be initialized implicitly depending on the type (e.g. pointer types get initialized to null pointers, arithmetic types get initialized to zero, and so on).
So, if you define an automatic variable without specifying an initial value for it, such as:
int myfunc(void) {
int myvar;
...
You are defining it (and therefore also declaring it, since definitions are declarations), but not initializing it. Therefore, definition does not equal declaration plus initialization.
"So does it mean definition equals declaration plus initialization."
Not necessarily, your declaration might be without any variable being initialized like:
void helloWorld(); //declaration or Prototype.
void helloWorld()
{
std::cout << "Hello World\n";
}
Related
After reading the question, I know the differences between declaration and definition. So does it mean definition equals declaration plus initialization?
Declaration
Declaration, generally, refers to the introduction of a new name in the program. For example, you can declare a new function by describing it's "signature":
void xyz();
or declare an incomplete type:
class klass;
struct ztruct;
and last but not least, to declare an object:
int x;
It is described, in the C++ standard, at §3.1/1 as:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
Definition
A definition is a definition of a previously declared name (or it can be both definition and declaration). For example:
int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };
Specifically the C++ standard defines it, at §3.1/1, as:
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-specification25 (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).
Initialization
Initialization refers to the "assignment" of a value, at construction time. For a generic object of type T, it's often in the form:
T x = i;
but in C++ it can be:
T x(i);
or even:
T x {i};
with C++11.
Conclusion
So does it mean definition equals declaration plus initialization?
It depends. On what you are talking about. If you are talking about an object, for example:
int x;
This is a definition without initialization. The following, instead, is a definition with initialization:
int x = 0;
In certain context, it doesn't make sense to talk about "initialization", "definition" and "declaration". If you are talking about a function, for example, initialization does not mean much.
So, the answer is no: definition does not automatically mean declaration plus initialization.
Declaration says "this thing exists somewhere":
int foo(); // function
extern int bar; // variable
struct T
{
static int baz; // static member variable
};
Definition says "this thing exists here; make memory for it":
int foo() {} // function
int bar; // variable
int T::baz; // static member variable
Initialisation is optional at the point of definition for objects, and says "here is the initial value for this thing":
int bar = 0; // variable
int T::baz = 42; // static member variable
Sometimes it's possible at the point of declaration instead:
struct T
{
static int baz = 42;
};
…but that's getting into more complex features.
For C, at least, per C11 6.7.5:
A declaration specifies the interpretation and attributes of a set of
identifiers. A definition of an identifier is a declaration for that
identifier that:
for an object, causes storage to be reserved for that object;
for a function, includes the function body;
for an enumeration constant, is the (only) declaration of the identifier;
for a typedef name, is the first (or only) declaration of the identifier.
Per C11 6.7.9.8-10:
An initializer specifies the initial value stored in an object ... if
an object that has automatic storage is not initialized explicitly,
its value is indeterminate.
So, broadly speaking, a declaration introduces an identifier and provides information about it. For a variable, a definition is a declaration which allocates storage for that variable.
Initialization is the specification of the initial value to be stored in an object, which is not necessarily the same as the first time you explicitly assign a value to it. A variable has a value when you define it, whether or not you explicitly give it a value. If you don't explicitly give it a value, and the variable has automatic storage, it will have an initial value, but that value will be indeterminate. If it has static storage, it will be initialized implicitly depending on the type (e.g. pointer types get initialized to null pointers, arithmetic types get initialized to zero, and so on).
So, if you define an automatic variable without specifying an initial value for it, such as:
int myfunc(void) {
int myvar;
...
You are defining it (and therefore also declaring it, since definitions are declarations), but not initializing it. Therefore, definition does not equal declaration plus initialization.
"So does it mean definition equals declaration plus initialization."
Not necessarily, your declaration might be without any variable being initialized like:
void helloWorld(); //declaration or Prototype.
void helloWorld()
{
std::cout << "Hello World\n";
}
This question is based on this question and this issue
The definition of variable relies on the term declaration of an object, but this is not clearly defined anywhere. Would it be synonymous with object declaration (and therefore only apply to a declaration introduced with a simple-declaration) and therefore make function parameter declaration not be variables, or is it something else?
The paragraph right before it defines declaration ([basic.5]) :
Every name that denotes an entity is introduced by a declaration.
ie. a declaration is something that introduces a name that denotes an entity.
A declaration of an object thus introduces a name that denotes an object.
Eg. :
int a; // a declaration of an object with name "a" -> a variable
The definition of parameter can be found in [defns.parameter] :
object or reference declared as part of a function declaration or definition or in the catch clause of an exception handler that acquires a value on entry to the function or handler
which matches the definition for variable ([basic.6]) :
A variable is introduced by the declaration of a reference other than a non-static data member or of an object.
Eg.
void foo(int a); // the parameter is a declaration of an object with name "a" -> a variable
I would like to initialize my private static member "pi" in the definition of the class in order to tidy my code better having the initializations in the .cpp files.
When I try this error shows up: "Declaration of constexpr static data member 'pi' requires an initializer"
I'm using CLion 2018.3.4 and C++ 11.
I tried to work around and the only solution is to initialize the member in the declaration.
Other answers on Stack Overflow provided me a better knowledge but didn't answer my question.
// .h file
class Shape {
public:
virtual void getArea();
private:
static constexpr float pi; // the error shows up here
};
// .cpp file
#include "Shape.h"
const float Shape::pi = 3.14; //here I don't exactly know why it does not require constexpr, but it's fine even with and without const
// what I think this is equivalent to (in .h file)
static constexpr float pi = 3.14;
I was expecting this to work like I was assigning "3.14" in the declaration.
I'm not defining a constructor, in that case I know it wouldn't work because the c'tor is meant to initialize an instance of the class while a static member is supposed to be already initialized being a global element in the "Shape" namespace.
What I suppose it is happening is that the linker tries to initialize the member in the header because it has to be done in the pre-processing phase while the .cpp file is used later.
With static constexpr members you cannot leave off the initializer in the class definition. A constexpr variable must be initialized when declared because it can be used after it is declared in a constant expression. This is detailed in [class.static.data]/3 of the C++11 standard
If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression ([expr.const]). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ] The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer.
emphasis mine
So, with that, your code needs to be
// .h file
class Shape {
public:
virtual void getArea();
private:
static constexpr float pi = 3.14; // we initialize here so it can be used.
};
// .cpp file
constexpr float Shape::pi; // we define here so it can be odr-used
Do note that this has changed in C++17. With the introduction of inline variables static constexpr member variables no longer need to be defined outside of the class. The compiler will handle it for you and ensure only a single defentition of the object exists. You can still define the member if you want, but that ability is deprecated and will most likely be removed in a future standard revision. The new text for [class.static.data]/3 is
If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression ([expr.const]). The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer. An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see [depr.static.constexpr]). Declarations of other static data members shall not specify a brace-or-equal-initializer.
emphasis mine
and [dcl.constexpr]/1 says that a static constexpr variable is implicitly inline
The constexpr specifier shall be applied only to the definition of a variable or variable template or the declaration of a function or function template. The consteval specifier shall be applied only to the declaration of a function or function template. A function or static data member declared with the constexpr or consteval specifier is implicitly an inline function or variable ([dcl.inline]). If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.
emphasis mine
After reading the question, I know the differences between declaration and definition. So does it mean definition equals declaration plus initialization?
Declaration
Declaration, generally, refers to the introduction of a new name in the program. For example, you can declare a new function by describing it's "signature":
void xyz();
or declare an incomplete type:
class klass;
struct ztruct;
and last but not least, to declare an object:
int x;
It is described, in the C++ standard, at §3.1/1 as:
A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.
Definition
A definition is a definition of a previously declared name (or it can be both definition and declaration). For example:
int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };
Specifically the C++ standard defines it, at §3.1/1, as:
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-specification25 (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).
Initialization
Initialization refers to the "assignment" of a value, at construction time. For a generic object of type T, it's often in the form:
T x = i;
but in C++ it can be:
T x(i);
or even:
T x {i};
with C++11.
Conclusion
So does it mean definition equals declaration plus initialization?
It depends. On what you are talking about. If you are talking about an object, for example:
int x;
This is a definition without initialization. The following, instead, is a definition with initialization:
int x = 0;
In certain context, it doesn't make sense to talk about "initialization", "definition" and "declaration". If you are talking about a function, for example, initialization does not mean much.
So, the answer is no: definition does not automatically mean declaration plus initialization.
Declaration says "this thing exists somewhere":
int foo(); // function
extern int bar; // variable
struct T
{
static int baz; // static member variable
};
Definition says "this thing exists here; make memory for it":
int foo() {} // function
int bar; // variable
int T::baz; // static member variable
Initialisation is optional at the point of definition for objects, and says "here is the initial value for this thing":
int bar = 0; // variable
int T::baz = 42; // static member variable
Sometimes it's possible at the point of declaration instead:
struct T
{
static int baz = 42;
};
…but that's getting into more complex features.
For C, at least, per C11 6.7.5:
A declaration specifies the interpretation and attributes of a set of
identifiers. A definition of an identifier is a declaration for that
identifier that:
for an object, causes storage to be reserved for that object;
for a function, includes the function body;
for an enumeration constant, is the (only) declaration of the identifier;
for a typedef name, is the first (or only) declaration of the identifier.
Per C11 6.7.9.8-10:
An initializer specifies the initial value stored in an object ... if
an object that has automatic storage is not initialized explicitly,
its value is indeterminate.
So, broadly speaking, a declaration introduces an identifier and provides information about it. For a variable, a definition is a declaration which allocates storage for that variable.
Initialization is the specification of the initial value to be stored in an object, which is not necessarily the same as the first time you explicitly assign a value to it. A variable has a value when you define it, whether or not you explicitly give it a value. If you don't explicitly give it a value, and the variable has automatic storage, it will have an initial value, but that value will be indeterminate. If it has static storage, it will be initialized implicitly depending on the type (e.g. pointer types get initialized to null pointers, arithmetic types get initialized to zero, and so on).
So, if you define an automatic variable without specifying an initial value for it, such as:
int myfunc(void) {
int myvar;
...
You are defining it (and therefore also declaring it, since definitions are declarations), but not initializing it. Therefore, definition does not equal declaration plus initialization.
"So does it mean definition equals declaration plus initialization."
Not necessarily, your declaration might be without any variable being initialized like:
void helloWorld(); //declaration or Prototype.
void helloWorld()
{
std::cout << "Hello World\n";
}
I was going to file a bug against GCC, but then realized that if my interpretation of the Standard is correct, it's a core language defect, not a compiler bug.
When a static data member of array type is defined outside class scope, identifiers in the array bound are looked up in class scope.
§9.4.2 [class.static.data] says "The initializer expression in the definition of a static data member is in the scope of its class (3.3.7)," but doesn't say anything about the declarator itself. It seems that this is the only name lookup context within a declarator.
§8.4.2 [dcl.array] doesn't mention the scope of the array bound, so by default the expression is evaluated in the enclosing scope, which is the namespace.
class X {
static int const size = some_complicated_metafunction<>::value;
static int arr[ size ];
};
// "size" should be qualified as "X::size", which is an access violation.
int X::arr[ size ] = {};
The problem is that if the array bound is not evaluated in class scope, there is no way to access private class members, and some_complicated_metafunction<> would have to be respecified. The array bound needs the same scope as the initializer, for essentially the same reason as the initializer. (Although not quite as strong, since constant expressions can always be recomputed, unlike the address of a private object.)
Am I missing something or is a DR in order?
I think the array bound in a member definition is in class scope. Standard 3.3.7/1:
The following rules describe the scope of names declared in classes.
...
5) The potential scope of a declaration that extends to or past the end of a class definition also extends to the regions defined by its member definitions, even if the members are defined lexically outside the class (this includes static data member definitions, nested class definitions, member function definitions (including the member function body and any portion of the declarator part of such definitions which follows the declarator-id, including a parameter-declaration-clause and any default arguments (8.3.6). ...
Here the declarator-id is X::arr.