I generally see examples of initialisation vs assignment like this:
int funct1(void)
{int a = 5; /*initialization*/
a = 6;} /*assignment*/
Obviously something left as garbage or undefined somehow is uninitialized.
But could some one please define if initialization is reserved for definition statements and/or whether assignments can be called initialisation?
int funct2(void)
{int b;
b = 5;} /*assignment, initialization or both??*/
Is there much of a technical reason why we can't say int b is initialised to garbage (from the compilers point of view)?
Also if possible could this be compared with initializing and assinging on non-primitive data types.
I'll resurrect this thread to add an important point of view, since the puzzlement about terminology by the OP is understandable. As #OliCharlesworth pointed out (and he's perfectly right about that) as far as the C language standard is concerned initialization and assignment are two completely different things. For example (assuming local scope):
int n = 1; // definition, declaration and **initialization**
int k; // just definition + declaration, but no initialization
n = 12; // assignment of a previously initialized variable
k = 42; // assignment of a previously UNinitialized variable
The problem is that many books that teach programming aren't so picky about terminology, so they call "initialization" any "operation" that gives a variable its first meaningful value. So, in the example above, n = 12 wouldn't be an initialization, whereas k = 42 would. Of course this terminology is vague, imprecise and may be misleading (although it is used too often, especially by teachers when introducing programming to newbies). As a simple example of such an ambiguity let's recast the previous example taking global scope into account:
// global scope
int n = 1; // definition, declaration and **initialization**
int k; // definition, declaration and **implicit initialization to 0**
int main(void)
{
n = 12; // assignment of a previously initialized variable
k = 42; // assignment of a previously initialized variable
// ... other code ...
}
What would you say about the assignments in main? The first is clearly only an assignment, but is it the second an initialization, according to the vague, generic terminology? Is the default value 0 given to k its first "meaningful" value or not?
Moreover a variable is commonly said to be uninitialized if no initialization or assignment has been applied to it. Given:
int x;
x = 42;
one would commonly say that x is uninitialized before the assignment, but not after it. The terms assignment and initializer are defined syntactically, but terms like "initialization" and "uninitialized" are often used to refer to the semantics (in somewhat informal usage). [Thanks to Keith Thompson for this last paragraph].
I dislike this vague terminology, but one should be aware that it is used and, alas, not too rare.
As far as the language standard is concerned, only statements of the form int a = 5; are initialisation. Everything of the form b = 5; is an assignment.
The same is true of non-primitive types.
And to "Is there much of a technical reason why we can't say int b is initialised to garbage", well, if you don't put any value into a memory location, it's not "initialisation". From the compiler's point of view, no machine language instruction is generated to write to the location, so nothing happens.
Related
The C++ reference pages say that () is for value initialisation, {} is for value and aggregate and list initialisation. So, if I just want value initialisation, which one do I use? () or {}? I'm asking because in the book "A Tour of C++" by Bjarne himself, he seems to prefer using {}, even for value initialisation (see for example pages 6 and 7), and so I thought it was good practice to always use {}, even for value initialisation. However, I've been badly bitten by the following bug recently. Consider the following code.
auto p = std::make_shared<int>(3);
auto q{ p };
auto r(p);
Now according to the compiler (Visual Studio 2013), q has type std::initializer_list<std::shared_ptr<int>>, which is not what I intended. What I actually intended for q is actually what r is, which is std::shared_ptr<int>. So in this case, I should not use {} for value initialisation, but use (). Given this, why does Bjarne in his book still seem to prefer to use {} for value initialisation? For example, he uses double d2{2.3} at the bottom of page 6.
To definitively answer my questions, when should I use () and when should I use {}? And is it a matter of syntax correctness or a matter of good programming practice?
Oh and uh, plain English if possible please.
EDIT:
It seems that I've slightly misunderstood value initialisation (see answers below). However the questions above still stands by and large.
Scott Meyers has a fair amount to say about the difference between the two methods of initialization in his book Effective Modern C++.
He summarizes both approaches like this:
Most developers end up choosing one kind of delimiter as a default, using
the other only when they have to. Braces-by-default folks are
attracted by their unrivaled breadth of applicability, their
prohibition of narrowing conversions, and their immunity to C++’s most
vexing parse. Such folks understand that in some cases (e.g., creation
of a std::vector with a given size and initial element value),
parentheses are required. On the other hand, the go-parentheses-go
crowd embraces parentheses as their default argument delimiter.
They’re attracted to its consistency with the C++98 syntactic
tradition, its avoidance of the auto-deduced-a-std::initializer_list
problem, and the knowledge that their object creation calls won’t be
inadvertently waylaid by std::initializer_list constructors. They
concede that sometimes only braces will do (e.g., when creating a
container with particular values). There’s no consensus that either
approach is better than the other, so my advice is to pick one and
apply it consistently.
This is my opinion.
When using auto as type specifier, it's cleaner to use:
auto q = p; // Type of q is same as type of p
auto r = {p}; // Type of r is std::initializer_list<...>
When using explicit type specifier, it's better to use {} instead of ().
int a{}; // Value initialized to 0
int b(); // Declares a function (the most vexing parse)
One could use
int a = 0; // Value initialized to 0
However, the form
int a{};
can be used to value initialize objects of user defined types too. E.g.
struct Foo
{
int a;
double b;
};
Foo f1 = 0; // Not allowed.
Foo f1{}; // Zero initialized.
First off, there seems to a terminology mixup. What you have is not value initialisation. Value initialisation happens when you do not provide any explicit initialisation arguments. int x; uses default initialisation, the value of x will be unspecified. int x{}; uses value initialisation, x will be 0. int x(); declares a function—that's why {} is preferred for value initialisation.
The code you've shown does not use value initialisation. With auto, the safest thing is to use copy initialisation:
auto q = p;
There is another important difference: The brace initializer requires that the given type can actually hold the given value. In other words, it forbids narrowing of the value, like rounding or truncation.
int a(2.3); // ok? a will hold the value 2, no error, maybe compiler warning
uint8_t c(256); // ok? the compiler should warn about something fishy going on
As compared to the brace initialization
int A{2.3}; // compiler error, because int can NOT hold a floating point value
double B{2.3}; // ok, double can hold this value
uint8_t C{256}; // compiler error, because 8bit is not wide enough for this number
Especially in generic programming with templates you should therefore use brace initialization to avoid nasty surprises when the underlying type does something unexpected to your input values.
{} is value initialization if empty, if not it is list/aggregate initialization.
From the draft, 7.1.6.4 auto specifier, 7/... Example,
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
Rules are a little bit complex to explain here (even hard to read from the source!).
Herb Sutter seems to be making an argument in CppCon 2014 (39:25 into the talk) for using auto and brace initializers, like so:
auto x = MyType { initializers };
whenever you want to coerce the type, for left-to-right consistency in definitions:
Type-deduced: auto x = getSomething()
Type-coerced: auto x = MyType { blah }
User-defined literals auto x = "Hello, world."s
Function declaration: auto f { some; commands; } -> MyType
Named Lambda: using auto f = [=]( { some; commands; } -> MyType
C++11-style typedef: using AnotherType = SomeTemplate<MyTemplateArg>
Scott Mayers just posted a relevant blog entry Thoughts on the Vagaries of C++ Initialization. It seems that C++ still has a way to go before achieving a truly uniform initialization syntax.
I tend to use the words define, declare and assign interchangeably but this seems to cause offense to some people. Is this justified? Should I only use the word declare for the first time I assign to a variable? Or is there more to it than that?
A definition is where a value or function is described, i.e. the compiler or programmer is told precisely what it is, e.g.
int foo()
{
return 1;
}
int var; // or, e.g. int var = 5; but this is clearer.
A declaration tells the compiler, or programmer that the function or variable exists. e.g.
int foo();
extern int var;
An assignment is when a variable has its value set, usually with the = operator. e.g.
a = b;
a = foo();
Define and declare are similar but assign is very different.
Here I am declaring (or defining) a variable:
int x;
Here I am assigning a value to that variable:
x = 0;
Here I am doing both in one statement:
int x = 0;
Note
Not all languages support declaration and assignment in one statement:
T-SQL
declare x int;
set x = 0;
Some languages require that you assign a value to a variable upon declaration. This requirement allows the compiler or interpreter of the language to infer a type for the variable:
Python
x = 0
It is important to use the correct terminology, otherwise people will not know what you are talking about, or incorrectly assume that you don't know what you are talking about.
These terms often have precise meanings in the standards for various languages. When that is the case they should not be conflated.
In c for instance:
a function may be defined only once (when you say what it does), but it may also be declared before that (when you say what arguments it takes and what type it returns).
likewise a variable is declared when you say what type it is, and this happens only once for each scope. But you may assign a value repeatedly. (Some languages also differentiate between initialization (giving a variable a value at declaration time) and assignment (changing the value later).)
General Role:
Definition = declaration + reserved space.
Definition, declaration, and assignment have two cases:
for Variables.
for Functions.
For Variables:
-- Definition:
To tell the compiler to reserve memory for the variable.
int x;
-- Declaration:
To tell the compiler that the variable defined in somewhere else.
extern int x;
-- Assignment:
To tell the compiler to put the value in the variable.
x = 0;
For Functions:
-- Definition:
int functionDef(int x){
int x;
...
...
...
return x;
}
-- Declaration:
It is just the prototype of the function.
int functionDef(int x);
The differences can seem subtle, but they are important. Not every language makes the same distinctions, but in C++ a variable declaration makes the type and name of the variable known to the compiler
int i;
A variable definition allocates storage and specifies an initial value for the variable.
i = 1;
You can combine a variable declaration and definition into one statement, as is commonly done.
int x = 1;
Declaring a variable inside a function will also set aside memory for the variable, so the following code implicitly defines variable a as a part of its declaration.
int main()
{
int a;
return 0;
}
Since variable a is automatically defined by the compiler, it will contain whatever value was in the memory location that was allocated for it. This is why it is not safe to use automatic variables until you've explicitly assigned a known value to them.
An assignment takes place any time you change the value of a variable in your program.
x = 2;
x++;
x += 4;
A function declaration, similar to the variable declaration, makes the function signature known to the compiler. This allows you to call a function in your source code before it is defined without causing a compiler error.
int doSomething(float x);
A function definition specifies the return type, name, parameter list, and instructions for a function. The first three of these elements must match the function declaration. A function must only be defined once in a given program.
int doSomething(float x)
{
if( x < 0 )
{
x = -x;
}
return static_cast<int>(x);
}
You can combine the function decalartion and definition into one, but you must do so before the function is called anywhere in your program.
It might depend on the language, as has been said. I think it really depends on whether the words are used for things like classes. For most of the data types discussed here, the question might not have much relevance. In C++ (see c++ - What is the difference between a definition and a declaration?), a class or struct always has precisely one definition but can be declared zero or more times. A class cannot be declared without a definition. So "declared" might be synonymous with "used".
In most languages, simple types such as integers do not need definitions in the manner that classes do.
The correct answer depends on which language you're talking about. Computer languages often have specific terminology, either because of the language specification or the community grown up around the language. COBOL, back when I used it, had a much different terminology than more mainstream languages (in the sense of languages closer to the mainstream of language development, not mainstream business). Forth developed some strange terminology.
If you know English, you can usually get a good idea as to what a word means from its normal meaning, but never count on it too much. The same is true with specific words across languages or language communities.
What is the difference in generated code when I have the definition of a variable at the top of a function and when I have it declared later. Example:
int f(int parameter) {
int a = parameter * 2;
if (a == 4)
return 1;
int b = parameter * 4;
if (b == 4)
return 2;
return 0;
}
Does output code have b variable initialization and allocation after if (a == 4) or will a and b variables be initialized at the same moment?.
To see what actually happens, look at the generated assembler.
In terms of allocating space, most compilers will allocate enough space on the stack for all the variables used in a function at the start of the function. (This doesn't have to happen like this, but I don't know of any compiler which don't work like this.)
In terms of initializations, the abstract machine (as defined by the C and C++ standards) treats the initializations (that is, setting the initial values) as happening at different times. b is initialized after the comparison of a with 4.
Of course, by the as-if rule, if the initialization doesn't have side-effects, the compiler can move the initialization round as it sees fit. This happens more often with C than with C++, because C++ initializers often involve constructors in other translation units, and the compiler can't see if there are side effects there.
In this simple case if you optimize, it is quite likely that both a and b will only ever be stored in a register, and this may well be the same register. (This is because you are using plain int variables, and because you don't overlap the use of a and b.)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a difference in C++ between copy initialization and direct initialization?
I just started to learn C++.
To initialize a variable with a value, I came across
int a = 0;
and
int a(0);
This confuses me a lot. May I know which is the best way?
int a = 0; and int a(0); make no difference in the machine generated code. They are the same.
Following is the assembly code generated in Visual Studio
int a = 10; // mov dword ptr [a],0Ah
int b(10); // mov dword ptr [b],0Ah
They're both the same, so there really is no one "best way".
I personally use
int a = 0;
because I find it more clear and it's more widely used in practice.
This applies to your code, where the type is int. For class-types, the first is copy-initialization, whereas the other is direct-initialization, so in that case it would make a difference.
There's no "best" way. For scalar types (like int in your example) both forms have exactly the same effect.
The int a(0) syntax for non-class types was introduced to support uniform direct-initialization syntax for class and non-class types, which is very useful in type-independent (template) code.
In non-template code the int a(0) is not needed. It is completely up to you whether you want to use the int a(0) syntax, or prefer to stick to more traditional int a = 0 syntax. Both do the same thing. The latter is more readable, in my opinion.
From a practical point of view: I would only use int a = 0;.
The int a(0) may be allowed but never used in practice in itself.
I think it should not bother you on your level, but let us go further.
Let's say that a is a class, not an int.
class Demo{
public:
Demo(){};
Demo(int){};
};
Demo a;
Demo b(a);
Demo c = a; // clearly expressing copy-init
In this example both b(a) and c=a do the same, and I would discourage you using the fist solution. My reason is, that is looks similar to c(2) which is a construction from arguments.
There are only two valid uses of this bracket-style initialization:
initialization lists (Demo(int i):data(i){} if Demo has an int data member data),
new's: Demo *p=new Demo(a); // copy constructing a pointer
It’s that simple. (Well, almost — there are a few things you can’t name your variables, which we’ll talk about in the next section)
You can also assign values to your variables upon declaration. When we assign values to a variable using the assignment operator (equals sign), it’s called an explicit assignment:
int a= 5; // explicit assignment
You can also assign values to variables using an implicit assignment:
int a(5); // implicit assignment
Even though implicit assignments look a lot like function calls, the compiler keeps track of which names are variables and which are functions so that they can be resolved properly.
In textbooks and literature, one is direct initialization and the other is copy initialization. But, in terms of machine code, there is no difference.
The difference is that () initialization is when you explicitly want it to take one parameter only, e.g:
You can:
int a = 44 + 2;
but you can't:
int a(44) + 2;
I tend to use the words define, declare and assign interchangeably but this seems to cause offense to some people. Is this justified? Should I only use the word declare for the first time I assign to a variable? Or is there more to it than that?
A definition is where a value or function is described, i.e. the compiler or programmer is told precisely what it is, e.g.
int foo()
{
return 1;
}
int var; // or, e.g. int var = 5; but this is clearer.
A declaration tells the compiler, or programmer that the function or variable exists. e.g.
int foo();
extern int var;
An assignment is when a variable has its value set, usually with the = operator. e.g.
a = b;
a = foo();
Define and declare are similar but assign is very different.
Here I am declaring (or defining) a variable:
int x;
Here I am assigning a value to that variable:
x = 0;
Here I am doing both in one statement:
int x = 0;
Note
Not all languages support declaration and assignment in one statement:
T-SQL
declare x int;
set x = 0;
Some languages require that you assign a value to a variable upon declaration. This requirement allows the compiler or interpreter of the language to infer a type for the variable:
Python
x = 0
It is important to use the correct terminology, otherwise people will not know what you are talking about, or incorrectly assume that you don't know what you are talking about.
These terms often have precise meanings in the standards for various languages. When that is the case they should not be conflated.
In c for instance:
a function may be defined only once (when you say what it does), but it may also be declared before that (when you say what arguments it takes and what type it returns).
likewise a variable is declared when you say what type it is, and this happens only once for each scope. But you may assign a value repeatedly. (Some languages also differentiate between initialization (giving a variable a value at declaration time) and assignment (changing the value later).)
General Role:
Definition = declaration + reserved space.
Definition, declaration, and assignment have two cases:
for Variables.
for Functions.
For Variables:
-- Definition:
To tell the compiler to reserve memory for the variable.
int x;
-- Declaration:
To tell the compiler that the variable defined in somewhere else.
extern int x;
-- Assignment:
To tell the compiler to put the value in the variable.
x = 0;
For Functions:
-- Definition:
int functionDef(int x){
int x;
...
...
...
return x;
}
-- Declaration:
It is just the prototype of the function.
int functionDef(int x);
The differences can seem subtle, but they are important. Not every language makes the same distinctions, but in C++ a variable declaration makes the type and name of the variable known to the compiler
int i;
A variable definition allocates storage and specifies an initial value for the variable.
i = 1;
You can combine a variable declaration and definition into one statement, as is commonly done.
int x = 1;
Declaring a variable inside a function will also set aside memory for the variable, so the following code implicitly defines variable a as a part of its declaration.
int main()
{
int a;
return 0;
}
Since variable a is automatically defined by the compiler, it will contain whatever value was in the memory location that was allocated for it. This is why it is not safe to use automatic variables until you've explicitly assigned a known value to them.
An assignment takes place any time you change the value of a variable in your program.
x = 2;
x++;
x += 4;
A function declaration, similar to the variable declaration, makes the function signature known to the compiler. This allows you to call a function in your source code before it is defined without causing a compiler error.
int doSomething(float x);
A function definition specifies the return type, name, parameter list, and instructions for a function. The first three of these elements must match the function declaration. A function must only be defined once in a given program.
int doSomething(float x)
{
if( x < 0 )
{
x = -x;
}
return static_cast<int>(x);
}
You can combine the function decalartion and definition into one, but you must do so before the function is called anywhere in your program.
It might depend on the language, as has been said. I think it really depends on whether the words are used for things like classes. For most of the data types discussed here, the question might not have much relevance. In C++ (see c++ - What is the difference between a definition and a declaration?), a class or struct always has precisely one definition but can be declared zero or more times. A class cannot be declared without a definition. So "declared" might be synonymous with "used".
In most languages, simple types such as integers do not need definitions in the manner that classes do.
The correct answer depends on which language you're talking about. Computer languages often have specific terminology, either because of the language specification or the community grown up around the language. COBOL, back when I used it, had a much different terminology than more mainstream languages (in the sense of languages closer to the mainstream of language development, not mainstream business). Forth developed some strange terminology.
If you know English, you can usually get a good idea as to what a word means from its normal meaning, but never count on it too much. The same is true with specific words across languages or language communities.