1

Per cppreference, the syntax for value initialization is:

  • [..]
  • T object {}; (since C++11)
  • [..]

It's already known that value-initialization is performed when an object is constructed with an empty initializer.

Per, [dcl.init]/8 (emphasis mine)

To value-initialize an object of type T means:

  • (8.1) if T is a (possibly cv-qualified) class type ([class]), then
    • (8.1.1) if T has either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
    • (8.1.2) otherwise, the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
  • (8.2) [..]
  • (8.3) [..]

I interpret the term "no default constructor" as that there's no default constructor declared in the class. For example,

class S
{
    long double d;
    friend void f(const S&);
};

void f(const S& s) { std::cout << s.d; }

int main()
{
    S s{ };
    f(s); // 0
}

Since the class has "no default constructor", I'm expecting that the object s is default-initialized and the member s.d has indeterminate value. Why that's not the case?

I also have a confusion in understanding the point (8.1.1). How I can write this line of code T object {} without having a default constructor or with having a deleted default constructor? Notice the bold part, It's said that, "if T has either no default constructor or a default constructor that is deleted .."

Are there situations where objects of class types are value-initialized with deleted default constructor or without default constructor at all? Am I misreading 8.1.1?

mada
  • 1,646
  • 1
  • 15
  • 1
    In case of, "if T has no default constructor": That would be by declaring something like `S::S(...)`. – mada Sep 07 '22 at 19:25
  • 1
    "_Why that's not the case?_" because, per [class.default.ctor]/1, an explicitly-defaulted default constructor is implicitly-declared `S() = default`. Then the object gets zero-initialized per (8.1.2). – mada Sep 07 '22 at 19:44
  • Check the rules for [automatic generation of special member functions](https://stackoverflow.com/a/24512883/2567683) (your case falls into "user declares nothing") – Nikos Athanasiou Sep 07 '22 at 20:09

1 Answers1

2

Your class S does have a default constructor; it is just defined implicitly.

Per [class.default.ctor]/1:

A default constructor for a class X is a constructor of class X for which each parameter that is not a function parameter pack has a default argument (including the case of a constructor with no parameters). If there is no user-declared constructor for class X, a non-explicit constructor having no parameters is implicitly declared as defaulted ([dcl.fct.def]). An implicitly-declared default constructor is an inline public member of its class.

Therefore S{} will zero-initialize the object per [dcl.init]/8.1.2.

When [dcl.init]/8.1.1 refers to classes with no default constructor it means classes where the implicit default constructor doesn't get generated because user-defined constructors exist. That is, (8.1.1) would apply to the following classes:

struct NoDefaultCtor
{
    NoDefaultCtor(int) {}
};

struct UserProvidedDefaultCtor
{
    UserProvidedDefaultCtor() {}
};

struct DeletedDefaultCtor
{
    DeletedDefaultCtor() = delete;
};

For all three of those classes, value-initialization will perform default-initialization. In the case of NoDefaultCtor and DeletedDefaultCtor that default-initialization will fail, of course, but it's important that (8.1.1) catches those types so they don't fall through and get zero-initialized by (8.1.2).

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • _"For all three of those classes, value-initialization will perform default-initialization."_ Why? – mada Sep 07 '22 at 19:57
  • @John Because \[dcl.init]/8.1.1 says so. If a class has no default constructor, a user-provided default constructor, or a deleted default constructor then value-initialization becomes default-initialization. Like you said, value-initialization/default-initialization will fail for `NoDefaultCtor` and `DeletedDefaultCtor`, but that doesn't mean it isn't performed (just that it fails when attempted). – Miles Budnek Sep 07 '22 at 20:01
  • When It's said "deleted", it doesn't said implicitly deleted or explicitly, so `S(const S&)` will apply (8.1.1) as the default one gets implicitly deleted. Right? In such case, the value-initialization will success and the default-initialization will apply also. Right? – mada Sep 07 '22 at 20:07
  • 1
    @John No, the implicit default constructor is only deleted when the conditions in [\[class.default.ctor\]/2](https://timsong-cpp.github.io/cppwp/n4861/class.default.ctor#2) are met (basically if the class has members that can't be default-initialized). When a class has a user-declared constructor no implicit default constructor is ever generated at all. – Miles Budnek Sep 07 '22 at 20:12
  • 1
    _"When a class has a user-declared constructor no implicit default constructor is ever generated at all."_ Thanks for this. So I was think that, the default constructor _is_ generated then marked as deleted. – mada Sep 07 '22 at 20:16
  • _"When a class has a user-declared constructor no implicit default constructor is ever generated at all."_ Can you tell me where the standard says that (_if possible_)? – mada Sep 07 '22 at 20:18
  • @John It doesn't ever explicitly say one _doesn't_ get generated, but rather [class.default.ctor]/1 only says one _does_ get generated when there's no user-declared constructor (see the bolded part of the quote in my answer), so that's the only case where it happens. – Miles Budnek Sep 07 '22 at 20:21