2
class Entity
{
};

//Entity e(); This was a mistake
Entity e;

Entity e1 = Entity();

The second method looks like an anonymous object is created which in turn initializes e1,but i dont think that is what's happening.

David L
  • 23
  • 1
  • 7

2 Answers2

4

Before C++17

Entity e1 = Entity();

You're right about this one. A temporary, default-constructed Entity is created, then used to copy-initialise e1.

Since C++17

Despite appearances, that no longer creates a temporary, it only looks like it does. The semantics of the line are now that there is simply a declaration of an Entity called e1, initialised with no constructor arguments. The temporary isn't "optimised out": it no longer ever exists in the first place.

This may seem like a pedantic distinction, and in such a simple case it kind of is. But this so-called "mandatory elision" is a fundamental change to how temporaries are defined in the language, and does have broader ramifications elsewhere that are worth making yourself aware of if you start working on larger and more complex projects.


In any C++ version

Entity e();

This declares a function called e to return an Entity.

Yes, even if you put it in block scope.


Suggested approach

Just declare an Entity

Entity e;
Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35
  • `Entity e;` is different to `Entity e{};` or `Entity e = Entity();`, which might leave primitive members uninitialized (also of recursive members, or elements of a `std::array`), which could be unexpected and/or undesired. – t.niese Oct 05 '20 at 19:01
  • @t.niese While technically true, no class should be designed that way. In this particular instance, the OP wanted to compare specifically against `Entity e`, so we must assume they're happy to use it. – Asteroids With Wings Oct 05 '20 at 19:48
  • @AsteroidsWithWings zero initialization comes with a cost, that you may not want. There is e.g. `std:array` which is designed that way (but it is also the case in the `glm` library and others). And if you are not aware of that, and you think that `type t = type();` or `type t{};` looks strange and you replace it by `type t;` because it looks better/shorter, you might mess things up (which once happened in a project I participated in), the changes remained at first unnoticed despite unit tests, since those instances had by accident reused memory which was zero. – t.niese Oct 06 '20 at 06:08
  • @t.niese could you please provide us a link to those rules? – Jean-Baptiste Yunès Oct 06 '20 at 06:29
  • 1
    @Jean-BaptisteYunès it is partially described in [this answer](https://stackoverflow.com/a/27484598/1960455) to **Default Initialization Versus Zero Initialization** (with references to the corresponding parts in the specs) or on cppreference.com: [Zero initialization](https://en.cppreference.com/w/cpp/language/zero_initialization), [Default initialization](https://en.cppreference.com/w/cpp/language/default_initialization). `Entity e` - depending on the storage duration - means possibly indeterminate values for its members. – t.niese Oct 06 '20 at 08:48
  • @t.niese Thanks! I understand why `Entity e;` is different to `Entity e{};`and why `{}` are necessary! Too much subtleties... – Jean-Baptiste Yunès Oct 06 '20 at 09:28
  • @Jean-BaptisteYunès I don't say `type t;` is wrong and should not be used, there are many use-cases where `type t;` is exactly what you want. It is just important to know that there is a difference between `type t;` and `type t{};` one should be aware of. – t.niese Oct 06 '20 at 09:31
  • @t.niese I understood it well thanks. I would have mean that for "good" initialization `{}` are mandatory. – Jean-Baptiste Yunès Oct 06 '20 at 10:02
0

In case Entity does not have a user-defined default constructor (and the members don't have default values), then Entity e and Entity e1 = Entity(); have different results.

struct Entity
{
   int x;
};

int main() {
  Entity e;
  Entity e1 = Entity();

  std::cout << e.x << std::endl; // access to uninitialized member variable
  std::cout << e1.x << std::endl; // access to zero initialized member variable
}

Whether that is relevant or not depends on the class you use, and how you will use it.

If you use e.g. an std::array and you want the elements to be zero-initialized, you need to write std::array<int,5> a = std::array<int,5>() or std::array<int,5> a{}.

This is one of the reasons why AAA (almost always auto), is suggested (e.g. auto a = std::array<int,5>()) by some people like Herb Sutter.

t.niese
  • 39,256
  • 9
  • 74
  • 101