15

It's been rehashed over and over that primitive types don't have constructors. For example this _bar is not initialized to 0 when I call Foo():

class Foo{
    int _bar;
};

So obviously int() is not a constructor. But what is it's name?

In this example I would say i is: (constructed? initialized? fooed?)

for(int i{}; i < 13; ++i)

Loki Astari mentions here that the technique has some sort of name.

EDIT in response to Mike Seymour:

#include <iostream>

using namespace std;

class Foo{
    int _bar;
public:
    void printBar(){ cout << _bar << endl; }
};

int main()
{
    Foo foo;

    foo.printBar();

    Foo().printBar();

    return 0;
}

Running this code on Visual Studio 2013 yields:

3382592
3382592

Interestingly on gcc 4.8.1 yields:

134514651
0

Community
  • 1
  • 1
Jonathan Mee
  • 35,107
  • 16
  • 95
  • 241
  • 3
    As an expression, `int()` and `Foo()` grammatically are "explicit type conversions" in the "functional notation", just like `int(5)`, but with different rules. But I'd guess that only few people use that name to identify that feature. – dyp Dec 12 '14 at 12:41
  • Adding to dyp, and the reason I marked as duplicate (did not know it would just *close* it immediately!), `T()` creates a value-initialized *prvalue* – David Rodríguez - dribeas Dec 12 '14 at 14:01
  • 1
    On the difference between compilers, VS is wrong. The rules for *value-initialization* require that `Foo` is *zero-initialized*, and that in turn means that `_bar` needs to get the value 0 in `Foo()` – David Rodríguez - dribeas Dec 12 '14 at 14:03
  • @DavidRodríguez-dribeas Yeah there is a long exchange between [Mike Seymour](http://stackoverflow.com/users/204847/mike-seymour) and myself in the comments on his answer, through which I came to see that. – Jonathan Mee Dec 12 '14 at 14:09
  • 2
    @JonathanMee: VS is known to have issues with different forms of *value-initialization*. I had a set of test cases that failed there for some time, and in my company we work around the compiler in a few cases. – David Rodríguez - dribeas Dec 12 '14 at 14:14
  • 3
    Reopened the question, not truly a duplicate as the issue with this question is finding out that `T()` means *value-initialization*, rather than understanding what *value-initialization* means (which is the point of this other question: http://stackoverflow.com/questions/1613341/what-do-the-following-phrases-mean-in-c-zero-default-and-value-initializat ) – David Rodríguez - dribeas Dec 12 '14 at 14:24

3 Answers3

9

It's been rehashed over and over that primitive types don't have constructors.

That's right.

For example this bar is not initialized to 0 when I call Foo()

Yes it is. Foo() specifies value-initialisation which, for class like this with no user-provided constructor, means it's zero-initialised before initialising its members. So _bar ends up with the value zero. (Although, as noted in the comments, one popular compiler doesn't correctly value-initialise such classes.)

It would not be initialised if you were to use default-initialisation instead. You can't do that with a temporary; but a declared variable Foo f; or an object by new F will be default-initialised. Default-initialisation of primitive types does nothing, leaving them with an indeterminate value.

It would also not be initialised if the class had a user-provided default constructor, and that constructor didn't specifically initialise _bar. Again, it would be default-initialised, with no effect.

So obviously int() is not a constructor. But what is it's name?

As an expression, it's a value-initialised temporary of type int.

Syntactically, it's a special case of an "explicit type conversion (functional notation)"; but it would be rather confusing to use that term for anything other than a type conversion.

In this example I would say i is: (constructed? initialized? fooed?)

Initialised. List-initialised (with an empty list), value-initialised, or zero-initialised, if you want to be more specific.

Mike Seymour
  • 235,407
  • 25
  • 414
  • 617
  • @PiotrS.: Sorry, I didn't notice the `private` and used the wrong term. I'm sure it's still zero-initialised though. – Mike Seymour Dec 12 '14 at 12:32
  • @PiotrS.: Indeed it is: if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then **the object is zero-initialized** and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called. – Mike Seymour Dec 12 '14 at 12:34
  • 1
    `_bar` is not initialized to zero – galdin Dec 12 '14 at 12:35
  • 3
    @gldraphael: The entire class object is zero-initialised, which has the effect of initialising `_bar` to zero. – Mike Seymour Dec 12 '14 at 12:35
  • 1
    @MikeSeymour ah yes, you're right about the zero-initialization if the class has no user-provided construcor – Piotr Skotnicki Dec 12 '14 at 12:39
  • @MikeSeymour I added a public method to `Foo`: `void printBar(){ cout << _bar << endl; }` When I call `Foo().printBar()` I get gibberish, *not* 0. – Jonathan Mee Dec 12 '14 at 12:41
  • 2
    @JonathanMee: [I don't](http://ideone.com/ibIboe). Perhaps your compiler doesn't value-initialise the object according to the standard. – Mike Seymour Dec 12 '14 at 12:45
  • 1
    @JonathanMee or maybe you are not showing the exact class declaration, where different rules may apply – Piotr Skotnicki Dec 12 '14 at 12:46
  • @MikeSeymour I've edited the question to demonstrate the calling of `printBar`. – Jonathan Mee Dec 12 '14 at 12:53
  • 5
    @JonathanMee: Your compiler is broken: https://connect.microsoft.com/VisualStudio/feedback/details/484295 – Mike Seymour Dec 12 '14 at 12:59
  • @MikeSeymour I guess that's somehow a halfway bug with gcc too then? – Jonathan Mee Dec 12 '14 at 13:01
  • 4
    @JonathanMee: No, that's doing the right thing. The first is default-initialised, leaving it with an indeterminate value; the second is correctly zero-initialised. – Mike Seymour Dec 12 '14 at 13:02
  • @MikeSeymour I always thought those were the exact same. Thanks for the explanation. AND IF ANYONE FROM MICROSOFT IS LISTENING FIX YOUR COMPILER THIS WAS REPORTED 2 VERSIONS AGO!!! – Jonathan Mee Dec 12 '14 at 13:13
  • @MikeSeymour This is interesting: http://stackoverflow.com/q/22233148/2642059 Did the standard change for C++11? – Jonathan Mee Dec 12 '14 at 13:41
  • 1
    @JonathanMee: The wording changed in C++11, but the reality described by the wording changed in C++03. The introduction of value initialization was the only non-bug-fix change in C++03. Otherwise C++03 was just TC1, *Technical Corrigendum 1*, a large bug-fix of C++98. – Cheers and hth. - Alf Dec 12 '14 at 13:45
  • 4
    @JonathanMee As you can test [here](http://rise4fun.com/vcpp), it was successfully fixed in vc2015 – Predelnik Dec 12 '14 at 15:31
  • @Predelnik Only 7 years and 3 versions after the bug report, sweet. None the less, I didn't realize they'd publicly released the preview, that's exciting. – Jonathan Mee Dec 12 '14 at 15:37
  • @MikeSeymour: visit also http://stackoverflow.com/questions/3931312/value-initialization-and-non-pod-types – Destructor Jul 09 '15 at 14:38
  • @MikeSeymour The foundation for what I know of initialization in C++ comes from this answer (scary I know.) Anyway Apparently I've misunderstood something and had to ask a follow up here: http://stackoverflow.com/q/37732000/2642059 Perhaps you'd grace me with a bit more clarification. – Jonathan Mee Jun 09 '16 at 17:01
6

Here's what int() does (bearing in mind that, grammatically, int is a simple-type-specifier):

[C++11: 5.2.3/1]: A simple-type-specifier (7.1.6.2) or typename-specifier (14.6) followed by a parenthesized expression-list constructs a value of the specified type given the expression list. If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4). If the type specified is a class type, the class type shall be complete. If the expression list specifies more than a single value, the type shall be a class with a suitably declared constructor (8.5, 12.1), and the expression T(x1, x2, ...) is equivalent in effect to the declaration T t(x1, x2, ...); for some invented temporary variable t, with the result being the value of t as a prvalue.

Speaking colloquially, it represents the construction of a temporary int with an empty initialiser. I think you'd struggle to find a formal name for the entire construct, though.

This is not the same as int i{}, which is a full-fledged declaration of a named object with an initialiser: your i has been declared, constructed and initialised.

(I don't think that any of this is related to what Loki was saying in his comment on that linked answer.)

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
  • 4
    Uhm... You almost nailed it, except that the better quote would be the next paragraph: *The expression `T()`, where `T` is a single-type-specifier... creates a prvalue of the specified type, which is **value-initialized** * – David Rodríguez - dribeas Dec 12 '14 at 14:00
-1

You can call it a pseudo-constructor if you want, mirroring the terminology for destructor (pseudo-destructor calls are discussed in C++11 §5.2.4). Anyway, int() is the default value of type int, i.e. 0.

Re the assertion that "primitive types don't have constructors", that's a rather silly and impractical view. From a formal point of view primitive types don't have constructors, but those who cling to that assertion aren't that much into the formal, at all. Also, from a machine code point of view they don't, but again, to those who think that assertion is important, machine code is like magic. There is a difference, though, namely that from a machine code point of view also common non-primitive POD types can lack constructors (they do have constructors formally), and again I doubt that those who put that assertion forward are even aware of the issues, i.e. I don't think they're qualified to have an opinion. About the same kind of considerations go for any absolute terminological claim: you can be almost sure, when you hear such a claim, that those who make it have almost no idea about what's involved, and that the claim is just impractical & silly.

Instead, when you hear e.g. "constructed" or "constructor call" in the context of primitive types, think about what it meaningfully can mean. The formal is just a matter of definition. The important, except for language lawyer discussions where it anyway is a given, is to have a conceptual model that works.


All the above said, the expression T() is not a "constructor" formally, it's not a constructor at the machine code level, and it's not a constructor conceptually, in any meaningful conceptual model.

It can be a constructor call (indeed the definition of a default constructor is that it can be called, at the source code level, with no arguments), but note that there's no grammar category for constructor calls.

With all of the above in mind I would just call it a constructor call, and when there is a need to be more precise, for primitive type T I would call it a pseudo-constructor call.


And if anyone criticized me for that, I'd just challenge them to a duel.


Do note, regarding your statement that

it's been rehashed over and over that primitive types don't have constructors. For example this bar is not initialized to 0 when I call Foo()

the expression Foo() performs value initialization, so that the instance (in this case) is zeroed.

Regarding the general lack of initialization of local automatic variables of primitive types without initializers, you have the same situation with any type without a user defined constructor, and even when there is a used defined constructor if that constructor doesn't initialize things.

This sometimes comes as a shock to C++ beginners.

Cheers and hth. - Alf
  • 135,616
  • 15
  • 192
  • 304
  • 3
    @anonymous dowvoter: please state your disagreement openly, so I can show you the errors of your thinking. dunno if i can save you, but i'll try. :) – Cheers and hth. - Alf Dec 12 '14 at 13:15
  • @Cheersanhth.-Alf I'm not sure if I understood your last edit: "you have the same situation with any type without a user defined constructor" can you elaborate? – Jonathan Mee Dec 12 '14 at 13:19
  • @JonathanMee: I meant for the situation where a local isn't initialized. Sorry. I clarified that (the OP's incorrect assertion played havoc with this, I didn't see that his `Foo` was the type). – Cheers and hth. - Alf Dec 12 '14 at 13:21
  • Until reading you and [Mike Seymour](http://stackoverflow.com/users/204847/mike-seymour)'s comments I really didn't understand what "value-initialization" meant as far as a default ctor goes. – Jonathan Mee Dec 12 '14 at 13:24
  • 1
    @anonymous downvoter: That's like 3 downvotes with no explanation. We should get a duel going. Please stream, I will watch. – Jonathan Mee Dec 12 '14 at 14:33