Does "default" constructor mean "default parameters" or "provided by C++"? - c++

I'm confused on what "default constructors" are because I'm getting two meanings from both my class and also online.
1) We have written a constructor ourselves, but we made the parameters set to default values.
2) We have NOT written ANY construct at all, but we can still "pretend" like we did and initialize an instance of a class using a C++ "provided constructor"
If the case is #2, what happens when you initialize? Garbage values?
Thanks!

[class.ctor]/4:
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.
If you do not provide any constructors, then C++ will synthesize a (possibly deleted) default constructor. The semantics of this synthesized constructor is specified in [class.ctor]/7:
A default constructor that is defaulted and not defined as deleted is
implicitly defined when it is odr-used to create an object of its class type ([intro.object]) or when it is explicitly defaulted after
its first declaration. The implicitly-defined default constructor
performs the set of initializations of the class that would be
performed by a user-written default constructor for that class with no
ctor-initializer and an empty compound-statement. If that user-written default constructor would be ill-formed, the program is
ill-formed. If that user-written default constructor would satisfy the
requirements of a constexpr constructor, the implicitly-defined
default constructor is constexpr. Before the defaulted default
constructor for a class is implicitly defined, all the
non-user-provided default constructors for its base classes and its
non-static data members shall have been implicitly defined.
[ Note: An implicitly-declared default constructor has an
exception specification ([except.spec]). An explicitly-defaulted
definition might have an implicit exception specification, see
[dcl.fct.def]. — end note ]
Therefore, yes, the data members will be default initialized without an in-class member initializers. This leaves members of builtin types uninitialized.

Related

Does declaring a constexpr object marks the constructor as constexpr

I just a have a problem in understanding when the compiler marks the constructor as constexpr.
If I write the following program:
struct S{ S() {}; }
constexpr S s{ };
Does this mean that the default constructor is marked as constexpr?
An implicitly-defined constructor is a constructor defined by the compiler implicitly when some contexts are encountered (see below). But, an explicitly-defined constructor is a constructor defined by the user, not by the compiler.
Now per [class.default.ctor]/4:
A default constructor that is defaulted and not defined as deleted is
implicitly defined when it is odr-used ([basic.def.odr]) to create an
object of its class type ([intro.object]), when it is needed for
constant evaluation ([expr.const]), or when it is explicitly defaulted
after its first declaration. The implicitly-defined default
constructor performs the set of initializations of the class that
would be performed by a user-written default constructor for that
class with no ctor-initializer and an empty compound-statement. If
that user-written default constructor would be ill-formed, the program
is ill-formed. If that user-written default constructor would satisfy
the requirements of a constexpr constructor ([dcl.constexpr]), the
implicitly-defined default constructor is constexpr [..]
This paragraph just tells you that the non-deleted defaulted default constructor is implicitly-defined when it's odr-used or needed for constant evaluation or explicitly-defaulted after its first declaration.
Also, it tells you that that implicitly-defined constructor is the same as the user-written default constructor with an empty body and no member-initializer-list.
Then, it tells you that it's defined as constexpr if its corresponding user-written default constructor satisfies all of the [dcl.constexpr]/3 conditions.
That's, an implicitly or explicitly defaulted constructor will be implicitly-defined as constexpr if all requirements of [dcl.constexpr]/3 are met. On other hand, neither explicitly-defined nor explicitly-declared constructor is implicitly-defined as constexpr even if it satisfies all of [dcl.constexpr]/3 that's because you explicitly defined it. But if you explicitly mark it as constexpr, it will be a constexpr constructor, meanwhile, it shall satisfy all of [dcl.constexpr]/3 conditions.
So in your example:
struct S{ S() {}; }
constexpr S s{ };
That's ill-formed just because S is not a literal type and you're trying to call a non-constexpr constructor in a constant expression context which is not allowed per [const.expr]/(5.2)
A constructor is only (potentially) implicitly constexpr if either the whole constructor itself is implicitly declared or if it is defaulted with = default on its first declaration.
You are manually declaring the constructor and you are not defaulting it, so it will only be constexpr if you add the constexpr specifier to the declaration.
The shown constructor is therefore not constexpr and as a consequence constexpr S s{ }; will fail to compile because the initialization would call a non-constexpr constructor which isn't allowed in a constant expression. constexpr on a variable declaration does however require the initialization of the variable (including the evaluation of the initializer(s)) to be a constant expression.
The other answers give details about why the constructor in your snippet is not constexpr, and that's good to know.
However, I think, given how the question is phrased, that another answer is required.
Does declaring a constexpr object marks the constructor as constexpr
This means that you are thinking of the idea that the way you declare an object can affect the definition of its class.
That is not the case: once you write down the definition of a class, that's the definition, at it won't be altered by whatever objects of that class you declare/define.
In more complex scenario, when templates are involved, the code generated for a template class can depend on the objects you create; but the point is that you'd be talking of a templates class, whereas your question is about a class.

Value initialization without default constructor

I was wondering under which circumstances a class may have no default constructor but will still be value-initialized. The typical case for "no default ctor" is that a parametrized one is present and the default ctor is not defaulted (= default).
Quoting from the 2020 standard, chapter 9.4.1, Initializers/General (the latest draft contains equivalent wording):
To value-initialize an object of type T means:
(8.1) — if T is a (possibly cv-qualified) class type (Clause 11), then
(8.1.1) — if T has either no default constructor (11.4.5.2) or a default constructor that is user-provided or deleted, then the object is default-initialized;
And
11.4.5.2 Default constructors [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 (9.5)
I read this such that 8.1.1 does not refer to cases with no constructor at all (because, as 11.4.5.2 explains, a default constructor is then implicitly declared). Instead I understand it as "No default constructor at all" (including implicit ones).
Value-initialization happens with new()or brace-initialization, and for excess elements in arrays that are brace-initialized (as in struct T{}; T arr[1]{};).
Neither construct compiles when there is "no default constructor". Are there situations where objects of types without default constructor are value-initialized at all? Am I misreading 8.1.1?
It’s just saying that value-initializing an object of a class type that lacks a default constructor tries and fails to default-initialize it. Note that the alternative in the next bullet still default-initializes it after zero-initializing it, so it’s not default-initialized any more for not having a default constructor.
Depending on one’s interpretation of [class.default.ctor], it might also be considered to cover the case where a class can be default-initialized via a variadic constructor template:
struct A {
template<class ...TT> A(TT...);
};
auto a=A(); // value-initialization -> default-initialization

Class with no constructor (implicit or explicit)

As far as I know, you get an implicit default constructor if you do not declare any constructor yourself. As a job interview question I was asked for a situation where you do not declare a constructor but still do not get an implicit default constructor either. So you end up with a class without any constructors. It is supposed to be code that compiles, so the answer is not having a member variable that does itself not provide a default constructor. Any ideas? Searching through stack overflow and various C++ sites did not reveal anything. Also, as a hint the interviewer said it does not have to do with inheritance.
If my reading of the standard is correct, if the default constructor is not used, it won't get implicitly defined.
C++11 12.1.6:
A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration.
Also, a default constructor can be defined as "deleted", C++11 12.1.5:
A
defaulted default constructor for class X is defined as deleted if:
X is a union-like class that has a variant member with a non-trivial default constructor,
any non-static data member with no brace-or-equal-initializer is of reference type,
any non-variant non-static data member of const-qualified type (or array thereof) with no brace-orequal-initializer does not have a user-provided default constructor,
X is a union and all of its variant members are of const-qualified type (or array thereof),
X is a non-union class and all members of any anonymous union member are of const-qualified type
(or array thereof), or
any direct or virtual base class, or non-static data member with no brace-or-equal-initializer, has class
type M (or array thereof) and either M has no default constructor or overload resolution (13.3) as applied
to M’s default constructor results in an ambiguity or in a function that is deleted or inaccessible from
the defaulted default constructor.
For example, it would appear from the above that the following program is well-formed:
struct X {
X(int) {}
};
struct Y {
X x;
};
Here Y does not have an implicitly defined default constructor because it's both not used and defined as deleted.
No, there is no such trick, unless it's a catch in the exact wording of the question.
12.1p5:
If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted.
The implicitly declared default constructor might be defined as deleted, but it is still a member of the class.
Effective C++, Item 5: "These functions [ctor, dtor, copy ctor, copy assignment operator] are generated only if they are needed [...]"
According to that, if you have a class that has no declared ctors, and you do not create any instances of that class, then your class will have no constructor(s) at all.

In C++0x, do non-static data member initializers override the implicit copy constructor?

According to N2628 related to c++0x, non-static data member initializers can be overridden by explicitly defined constructors, but it appears to be slightly nebulous about the implicitly defined copy constructor.
In particular, I've noticed that with Apple clang version 3.0, the behavior varies depending on whether the struct (or class) is a POD.
The following program returns output "1", which indicates that the copy-constructor is ignoring the right-hand-side, and instead substituting the new non-static data member initializer (in this example, the boolean true value for X::a).
#include <iostream>
#include <string>
struct X
{
std::string string1;
bool a = true;
};
int main(int argc, char *argv[])
{
X x;
x.a = false;
X y(x);
std::cout << y.a << std::endl;
}
However, confusingly, if you comment out string1:
// std::string string1;
then the behavior works as I expected (the output is "0"), presumably because there is no implicitly generated copy-constructor, and therefore the data is copied.
Does the C++0x specification really suggest that it is a good idea to allow the implicitly defined copy-constructor to not copy the contents of the right-hand side? Isn't that less useful and unintuitive? I find the non-static member initializer functionality to be quite convenient, but if this is the correct behavior, then I will explicitly avoid the feature due to its tricky and unintuitive behavior.
Please tell me I'm wrong?
UPDATE: This bug has been fixed in the Clang source repository. See this revision.
UPDATE: This bug appears fixed in Apple clang version 3.1 (tags/Apple/clang-318.0.45) (based on LLVM 3.1svn). This version of clang was distributed as part of Xcode 4.3 for Lion.
It isn't shadowy after all, see highlighted parts of the standards excerpt:
The section on defaulted copy/move constructors (§ 12.8) is a bit too lengthy to quote in it's entirety. The low-down is that non-static member fields with initializers are still simply copied by the defaulted copy/move constructor
§ 12.8:
-6. The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move
of its bases and members. [ Note: brace-or-equal-initializers of non-static data members are ignored. See
also the example in 12.6.2. —end note ] The order of initialization is the same as the order of initialization
of bases and members in a user-defined constructor (see 12.6.2). Let x be either the parameter of the
constructor or, for the move constructor, an xvalue referring to the parameter. Each base or non-static data
member is copied/moved in the manner appropriate to its type:
if the member is an array, each element is direct-initialized with the corresponding subobject of x;
if a member m has rvalue reference type T&&, it is direct-initialized with static_cast(x.m);
otherwise, the base or member is direct-initialized with the corresponding base or member of x.
Virtual base class subobjects shall be initialized only once by the implicitly-defined copy/move constructor
This is the sample referred to:
struct A {
int i = /* some integer expression with side effects */;
A(int arg) : i(arg) { }
// ...
};
The A(int) constructor will simply initialize i to the value of arg, and the side effects in i’s brace-or-equalinitializer will not take place. —end example ]
For completeness, the corresponding section on the defaulted default constructor:
§ 12.1
-6. A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration.
The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty
compound-statement. If that user-written default constructor would be ill-formed, the program is ill-formed.
If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5),
the implicitly-defined default constructor is constexpr. Before the defaulted default constructor for a
class is implicitly defined, all the non-user-provided default constructors for its base classes and its nonstatic
data members shall have been implicitly defined. [ Note: An implicitly-declared default constructor
has an exception-specification (15.4). An explicitly-defaulted definition might have an implicit exception-specification,
see 8.4. —end note ]

defaulted default constructor ? in n3290 draft

A point from n3290 draft §12.1 (Constructors) ¶5:
An implicitly-declared default constructor is an inline public member of
its class. A defaulted default constructor for class X is defined as deleted
if:
X is a union-like class that has a variant member with a non-trivial
default constructor,
any non-static data member with no brace-or-equal-initializer is of
reference type,
any non-variant non-static data member of const-qualified type (or array
thereof) with no brace-or-equal-initializer does not have a user-provided
default constructor,
X is a union and all of its variant members are of const-qualified type
(or array thereof),
X is a non-union class and all members of any anonymous union member are of
const-qualified type (or array thereof),
any direct or virtual base class, or non-static data member with no
brace-or-equal-initializer, has class type M (or array thereof) and either
M has no default constructor or overload resolution (13.3) as applied
to M’s default constructor results in an ambiguity or in a function that is
deleted or inaccessible from the defaulted default constructor, or
any direct or virtual base class or non-static data member has a type with a
destructor that is deleted or inaccessible from the defaulted default constructor
Please explain the defaulted default constructor with some example program.
I think this excerpt from Wikipedia explains this:
Explicitly-defaulted and deleted special member functions
In C++03, the compiler provides, for classes that do not provide for themselves, a default constructor, a copy constructor, a copy assignment operator (operator=), and a destructor. The programmer can override these defaults by defining custom versions. C++ also defines several global operators (such as operator= and operator new) that work on all classes, which the programmer can override.
However, there is very little control over the creation of these defaults. Making a class inherently non-copyable, for example, requires declaring a private copy constructor and copy assignment operator and not defining them. Attempting to use these functions is a violation of the one definition rule. While a diagnostic message is not required,[5] this typically results in a linker error.[citation needed]
In the case of the default constructor, the compiler will not generate a default constructor if a class is defined with any constructors. This is useful in many cases, but it is also useful to be able to have both specialized constructors and the compiler-generated default.
C++11 will allow the explicit defaulting and deleting of these special member functions. For example, the following type explicitly declares that it is using the default constructor:
Code Example:
struct SomeType
{
SomeType() = default; //The default constructor is explicitly stated.
SomeType(OtherType value);
};
Since you seem to be a Standerdese fan(Almost all of your Questions seek explanations on Standard Quotes) this paper here about how standards committe arrive to defining default and deleted functions should be a good read for you:
Defaulted and Deleted Functions
One of the special member functions is "defaulted" if it is declared with the = default; syntax. The line right before the first line you quoted states:
If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted (8.4).
Therefore, a "defaulted" default constructor is a default constructor (constructor that can be called with no arguments) that is declared with = default. This can be explicitly defined using the = default syntax, or implicitly defined, per the above line.