Which of the following declaration is the standard and preferred?
int x = 7;
or
int x(7);
int x(7);
is not the valid way of declaring & initializing a variable in C;
I suggest you to get a good book for learning C and use a good compiler.
in c kind of langueges you normally use
int x = 7;
You've tagged this question as both C and C++, but the answers aren't really the same for the two.
In C, int x(7); simply doesn't work. It won't even compile. Since this form doesn't work at all in C, the preferred form is int x = 7;.
In C++, int x(7); works -- but you have to be careful, as this form can lead to the "most vexing parse"; if whatever was in the parentheses could be interpreted as a type instead of a value, this would be parsed as declaring a function named x that returned an int instead of defining an int with the value specified in the parentheses. Likewise, if you leave the parens empty: int x(); you end up with a function declaration.
C++ does have another form: int x{7};. Some call this "universal initialization". It does remove any ambiguity -- anything like T id { x }; where T is a type must be a definition of a id with x as an initializer. Some people dislike this, however, because it introduces somewhat different semantics -- for example, "narrowing" conversions are prohibited in this case, so you can't blindly change existing code to use the new form. For example:
int x(12.34); // no problem
int y{ 12.34 }; // won't compile -- double -> int is a narrowing conversion
This isn't particularly likely to happen with a literal as I've shown above, but something like:
void f(double x) {
int y(x);
// ...
...is rather more likely -- and still isn't allowed.
Unfortunately, going "back" to the C-style initialization doesn't cure all the possible problems either. At least in theory, it does copy initialization instead of direct initialization, so the type you're initializing must have a copy constructor available to do this initialization. For example:
class T {
T(T const &) = delete;
public:
T(int) {}
};
int main() {
T t = 1;
}
This isn't officially allowed to work, because what it's supposed to do is use T(int) to create a temporary T object, then use T(T const &) to copy-construct t from that temporary. Since we've deleted the copy constructor, it can't (officially) be used. This can be particularly confusing, because nearly all compilers will normally do the job without using the copy constructor at all, so the code will normally compile and work just fine--but the minute you turn on the mode where the compiler tries to follow the standard as closely as possible, the code won't compile at all.
Some people find the changes in "uniform initialization" so off-putting that they recommend against using it at all. Personally, I prefer to use it and simply ensure that I'm not doing any narrowing conversions (or use an explicit cast if a narrowing conversion just can't be avoided).
In general
int x = 7;
is the standard way, and the ONLY way in C.
However, in C++, you can initialize an int using x(7) in cases such as constructor initializer lists, where you have to invoke a 'constructor' for each variable you are initializing that way. For primitives, you do this with the x(7) syntax.
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.
From what I understand it is legal to instantiate an integer in c++ like this:
int x = int(5);
As a Java programmer I would assume that this line of code calls the constructor of the integer passing "5" as an argument. I read though that int is not a class and thus has no constructor.
So, what does exactly happen in that line of code and what is the fundamental difference between initialising the int that way and this way:
int x = 5;
Thanks in advance!
I read though that int is not a class and thus has no constructor.
Yes, technically built-in types have no constructor.
what does exactly happen in that line of code
The integer literal 5 is explicitly cast to an int (a no-op for the compiler mostly) and assigned to x.
what is the fundamental difference between initialising the int that way and int x = 5;
Essentially, no difference. All the below expressions are the same in most cases, unless you're a language lawyer (for instance, the last would prevent narrowing i.e. raise an error if the value cannot be represented by the type):
int x = 5; // copy initialization
int y = int(5); // cast and copy initialization
int z = (int)5; // cast and copy initialization
int w(5); // direct initialization
int r{5}; // direct initialization
Read more about initializations for finer details and differences.
C++ and java work differently when it comes to types. While java (to my understanding) uses basic built in types and reference types, C++ uses a different type system.
C++ built in types includes fundamental types (bool, character types like char, integer types, floating point types, and void) as well as some other types such as reference types like double& or std::vector<std::sting>&& and pointer types.
In addition to those, C++ supports user defined types (structs, classes, enum and enum class). the standard library provides many user defined types such as std::string.
it turns out the int a(5); notation is NOT reserved for user defined types only, The ,language supports value initialization that way. in C++11 it is also legal to say int a{5};
now about value assignment:
int a; //declaration
a=5; //assignment
int b(5); //declaration+initialization
int c=5; //declaration+initialization (NO assignment)
If a variable has not been declared, there is no assignment, the compiler parses int c=5; just like int c(5);
With C++11 came a new way to initialize and declare variables.
Original
int c_derived = 0;
C++11
int modern{0};
What are the pros and cons of each method, if there are any? Why implement a new method? Does the compiler do anything different?
You're mistaken -- the int modern(0) form (with round brackets) was available in older versions of C++, and continues to be available in C++11.
In C++11, the new form uses curly brackets to provide uniform initialisation, so you say
int modern{0};
The main advantage of this new form is that it can be consistently used everywhere. It makes it clear that you're initialising a new object, rather than calling a function or, worse, declaring one.
It also provides syntactical consistency with C-style ("aggregate") struct initialisation, of the form
struct A
{
int a; int b;
};
A a = { 1, 2 };
There are also more strict rules with regard to narrowing conversions of numeric types when the curly-bracket form is used.
Using braces was just an attempt to introduce universal initialization in C++11.
Now you can use braces to initialize arrays,variables,strings,vectors.
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 understand that the keyword explicit can be used to prevent implicit conversion.
For example
Foo {
public:
explicit Foo(int i) {}
}
My question is, under what condition, implicit conversion should be prohibited? Why implicit conversion is harmful?
Use explicit when you would prefer a compiling error.
explicit is only applicable when there is one parameter in your constructor (or many where the first is the only one without a default value).
You would want to use the explicit keyword anytime that the programmer may construct an object by mistake, thinking it may do something it is not actually doing.
Here's an example:
class MyString
{
public:
MyString(int size)
: size(size)
{
}
//... other stuff
int size;
};
With the following code you are allowed to do this:
int age = 29;
//...
//Lots of code
//...
//Pretend at this point the programmer forgot the type of x and thought string
str s = x;
But the caller probably meant to store "3" inside the MyString variable and not 3. It is better to get a compiling error so the user can call itoa or some other conversion function on the x variable first.
The new code that will produce a compiling error for the above code:
class MyString
{
public:
explicit MyString(int size)
: size(size)
{
}
//... other stuff
int size;
};
Compiling errors are always better than bugs because they are immediately visible for you to correct.
It introduces unexpected temporaries:
struct Bar
{
Bar(); // default constructor
Bar( int ); // value constructor with implicit conversion
};
void func( const Bar& );
Bar b;
b = 1; // expands to b.operator=( Bar( 1 ));
func( 10 ); // expands to func( Bar( 10 ));
A real world example:
class VersionNumber
{
public:
VersionNumber(int major, int minor, int patch = 0, char letter = '\0') : mMajor(major), mMinor(minor), mPatch(patch), mLetter(letter) {}
explicit VersionNumber(uint32 encoded_version) { memcpy(&mLetter, &encoded_version, 4); }
uint32 Encode() const { int ret; memcpy(&ret, &mLetter, 4); return ret; }
protected:
char mLetter;
uint8 mPatch;
uint8 mMinor;
uint8 mMajor;
};
VersionNumber v = 10; would almost certainly be an error, so the explicit keyword requires the programmer to type VersionNumber v(10); and - if he or she is using a decent IDE - they will notice through the IntelliSense popup that it wants an encoded_version.
Mostly implicit conversion is a problem when it allows code to compile (and probably do something strange) in a situation where you did something you didn't intend, and would rather the code didn't compile, but instead some conversion allows the code to compile and do something strange.
For example, iostreams have a conversion to void *. If you're bit tired and type in something like: std::cout << std::cout; it will actually compile -- and produce some worthless result -- typically something like an 8 or 16 digit hexadecimal number (8 digits on a 32-bit system, 16 digits on a 64-bit system).
At the same time, I feel obliged to point out that a lot of people seem to have gotten an almost reflexive aversion to implicit conversions of any kind. There are classes for which implicit conversions make sense. A proxy class, for example, allows conversion to one other specific type. Conversion to that type is never unexpected for a proxy, because it's just a proxy -- i.e. it's something you can (and should) think of as completely equivalent to the type for which it's a proxy -- except of course that to do any good, it has to implement some special behavior for some sort of specific situation.
For example, years ago I wrote a bounded<T> class that represents an (integer) type that always remains within a specified range. Other that refusing to be assigned a value outside the specified range, it acts exactly like the underlying intger type. It does that (largely) by providing an implicit conversion to int. Just about anything you do with it, it'll act like an int. Essentially the only exception is when you assign a value to it -- then it'll throw an exception if the value is out of range.
It's not harmful for the experienced. May be harmful for beginner or a fresher debugging other's code.
"Harmful" is a strong statement. "Not something to be used without thought" is a good one. Much of C++ is that way (though some could argue some parts of C++ are harmful...)
Anyway, the worst part of implicit conversion is that not only can it happen when you don't expect it, but unless I'm mistaken, it can chain... as long as an implicit conversion path exists between type Foo and type Bar, the compiler will find it, and convert along that path - which may have many side effects that you didn't expect.
If the only thing it gains you is not having to type a few characters, it's just not worth it. Being explicit means you know what is actually happening and won't get bit.
To expand Brian's answer, consider you have this:
class MyString
{
public:
MyString(int size)
: size(size)
{
}
// ...
};
This actually allows this code to compile:
MyString mystr;
// ...
if (mystr == 5)
// ... do something
The compiler doesn't have an operator== to compare MyString to an int, but it knows how to make a MyString out of an int, so it looks at the if statement like this:
if (mystr == MyString(5))
That's very misleading since it looks like it's comparing the string to a number. In fact this type of comparison is probably never useful, assuming the MyString(int) constructor creates an empty string. If you mark the constructor as explicit, this type of conversion is disabled. So be careful with implicit conversions - be aware of all the types of statements that it will allow.
I use explicit as my default choice for converting (single parameter or equivalent) constructors. I'd rather have the compiler tell me immediately when I'm converting between one class and another and make the decision at that point if the conversion is appropriate or instead change my design or implementation to remove the need for the conversion completely.
Harmful is a slightly strong word for implicit conversions. It's harmful not so much for the initial implementation, but for maintenance of applications. Implicit conversions allow the compiler to silently change types, especially in parameters to yet another function call - for example automatically converting an int into some other object type. If you accidentally pass an int into that parameter the compiler will "helpfully" silently create the temporary for you, leaving you perplexed when things don't work right. Sure we can all say "oh, I'll never make that mistake", but it only takes one time debugging for hours before one starts thinking maybe having the compiler tell you about those conversions is a good idea.