defaulted default constructor ? in n3290 draft - c++

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.

Related

Does "default" constructor mean "default parameters" or "provided by 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.

Is there any difference between virtual destructor=default and one with empty body?

A virtual destructor which does nothing is
virtual ~ClassName() {}
Since C++11 we can alternatively say:
virtual ~ClassName() = default;
Is there any difference between these two?
The main difference is that there are rules for defaulted functions that specify under which circumstances they are deleted (cf. ISO c++14(N4296) 8.4, 12.1, 12.4, 12.8)
8.4.2.5: Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the
implementation shall provide implicit definitions for them (12.1 12.4,
12.8), which might mean defining them as deleted.
e.g.:
12.4.5: A defaulted destructor for a class X is defined as deleted if:
(5.1) — X is a union-like class that has a variant member with a
non-trivial destructor, (5.2) — any potentially constructed subobject
has class type M (or array thereof) and M has a deleted destructor or
a destructor that is inaccessible from the defaulted destructor, (5.3)
— or, for a virtual destructor, lookup of the non-array deallocation
function results in an ambiguity or in a function that is deleted or
inaccessible from the defaulted destructor
In case your use falls into one of the deleted categories, using default will be equivalent to using delete whereas {} won't be.

Does it violate the standard for a non-default-constuctible struct to lack a user-defined constructor?

It is possible to define a struct (a) that has no user-defined constructors, and (b) for which a default constructor cannot be generated. For example, Foo in the below:
struct Baz
{
Baz(int) {}
};
struct Foo
{
int bar;
Baz baz;
};
You can still create instances of Foo using aggregate initialization:
Foo foo = { 0, Baz(0) };
My normal compiler (VS2012) will grudgingly accept this, but it raises 2 warnings:
warning C4510: 'Foo': default constructor could not be generated.
warning C4610: struct 'Foo' can never be instantiated - user defined constructor required
Of course, I've just proved warning #2 wrong--you can still instantiate it using aggregate initialization. The online compilers I've tried are happy enough to accept the above, so I'm guessing VS2012 is just being overly-aggressive with this warning. But I'd like to be sure--is this code ok, or does it technically violate some obscure part of the standard?
The standard explicitly allows cases like Foo in [12.1p4]:
[...] If there is no user-declared constructor for
class X, a constructor having no parameters is implicitly declared as defaulted [...] A defaulted default constructor for class X is defined as
deleted if:
[...]
any potentially constructed subobject, except for a non-static data member with a 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
[...]
Baz has no default constructor, so the emphasised part above applies (emphasis mine).
There's nothing 'undefined' or 'ill-formed' about such cases. The implicitly declared default constructor is defined as deleted, that's all. You could do the same thing explicitly, and it would still be just as valid.
The definition for aggregates is in [8.5.1p1]. For C++14, it is:
An aggregate is an array or a class (Clause 9) with no user-provided
constructors (12.1), no private or protected non-static data members
(Clause 11), no base classes (Clause 10), and no virtual functions
(10.3).
The 'no user-provided' part allows you to use = delete on all constructors that could possibly be implicitly declared (making them user-declared, but not user-provided) and the class would still be an aggregate, allowing you to use aggregate initialization on it.
As for warning C4610, I've encountered it before myself and reported it. As you can see, it's been fixed in the upcoming version of VC++.
It may be worth mentioning that the example I used in the bug report is taken directly from the standard, where it's treated as well-formed ([12.2p5.4]:
struct S { int mi; const std::pair<int,int>& mp; };
S a { 1, {2,3} };
This is similar to your case, but here, the implicitly declared default constructor is defined as deleted because the class has a non-static member of reference type that has no initializer.
Granted, it's only an example, but I think it's an additional indication that there's nothing wrong with these cases.
That's not actually aggregate initialization, it's uniform, which is only recently supported by VS. This warning is simply them not correctly updating it to reflect that that type can now be uniform initialized.
Aggregates may not have user-defined non-defaulted non-deleted constructors, and the rules for aggregate UDTs are that each member must also be an aggregate. Therefore, Baz is not an aggregate and as a direct result, neither can Foo be.

Understanding constructor concept

I don't understand what constructor means in C++ formally. I was reading 3.8 clause (Object lifetime, N3797) and come across with the following:
An object is said to have non-trivial initialization if it is of a
class or aggregate type and it or one of its members is initialized by
a constructor other than a trivial default constructor.
I would like to understand an initialization in general. I've read section 8.5, N3797. Is it true that if some object is initialized, a constructor (possibly trivial default) will be called? I mean that every initialization process (even zero-initialization) means constructor calling. It would be good if you provide corresponding references to the Standard.
I don't understand what contructor means in C++ formally.
As far as I know, the standard does not explicitly contain a definition of the term "constructor". However, §12.1/1 says
Constructors do not have names. A special declarator syntax is used to declare or define the constructor.
The syntax uses:
an optional decl-specifier-seq in which each decl-specifier is either a function-specifier or constexpr,
the constructor's class name, and
a parameter list
in that order. In such a declaration, optional parentheses around the constructor class name are ignored.
Thus, if you declare a member function according to this syntax, the function you are declaring is a constructor. In addition,
The default constructor (12.1), copy constructor and copy assignment operator (12.8), move constructor
and move assignment operator (12.8), and destructor (12.4) are special member functions. [ Note: The
implementation will implicitly declare these member functions for some class types when the program does
not explicitly declare them. The implementation will implicitly define them if they are odr-used (3.2).
See 12.1, 12.4 and 12.8. — end note ] Programs shall not define implicitly-declared special member functions.
(§12/1)
So there you go---every class has at least three constructors declared, whether implicitly or explicitly; and you can also declare other constructors using the syntax in §12.1/1. The entire set of functions thus declared forms the set of constructors.
Is it true that if some object is initialized, a constructor (possibly trivial default) will be called? I mean that every initialization process (even zero-initialization) means constructor calling.
No, this is false. For example, int has no constructors. This is despite the fact that you can initialize an int with similar syntax compared to initialization of objects of class type.
struct Foo {};
Foo f {}; // calls default constructor
int i {}; // sets the value of i to 0
Also, zero-initialization never invokes a constructor, but zero-initialization is also never the only step in the initialization of an object.
If by "object" you meant "object of class type", it is still not true that a constructor is always called, although three constructors are always declared, as stated above. See §8.5/7 on value initialization:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the
default constructor for T is called (and the initialization is ill-formed if T has no accessible default
constructor);
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.
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized.
Therefore, when the default constructor for a non-union class type is trivial and you are value-initializing an object of that type, the constructor really is not called.
Classes are types:
A class is a type.
§9 [class]
However, not all types are classes. The standard refers to types which are not class types (scalar types, for example) in §3.9.
Only class types, however, can have member functions:
Functions declared in the definition of a class, excluding those declared with a friend specifier, are called member functions of that class.
§9.3 [class.mfct]
Constructors are member functions. Therefore types without constructors can exist (i.e. types that are not class types). Therefore initialization does not necessarily involve calling a constructor, since non-class types (int for example) may be initialized.
Note that something does not have to be of class type to be an "object":
An object is a region of storage.
§1.8 [intro.object]
Therefore an int, while not being of class type, would be an "object".
I think your answer would be found in 3.6.2, and 8.5 of N3797.
A constructor is always called on object creation. But initialization of an object is
multi-step process.
I understand that Zero-Initialization is separate and performed as the first step during object initialization, the Constructor (possibly trivial default) is called later
A constructor is special function. It looks like a normal function. It doesn't have return type (though some say the return type is the object of the class) like void, int, char, double, etc. It has same name as name of Class. It runs automatically when object is created.
In C++, you don't need new operator to initialize an object. Just declare it and set its attribute. i.e. ClassA object1, object2;
For example
Class Player{
int jerseyNo;
//constructor
Player(){
cout<<"HELLO";
}
};
In main you can do the following:
Player nabin;
And you can declare destructor as well. Destructor is special function similar to constructor but runs when object is destroyed i.e. when object moves out of scope.
Example:
Class Player{
..
~Player(){
cout<<"Destructor ran";
}
..
};
P.S The order of execution of constructor and destructor is reverse.
Example:
Player p1,p2,p3;
The order of their execution
1. p1's constructor runs
2. p2's constructor runs
3. p3's constructor runs
4. p3's destructor runs
5. p2's destructor runs
6. p1's destructor runs
You asked:
Is it true that if some object is initialized, a constructor (possibly trivial default) will be called?
The short answer: No.
A longer answer: A constructor is called only for objects of class types. For objects of other types, there are no constructors, and hence constructors cannot be called.
You said:
I mean that every initialization process (even zero-initialization) means constructor calling.
Objects of class types can be initialized by calling constructors, which can be explicit or implicit. They can also be initialized by other initialization methods. Objects of other types are initialized by directly setting the initial values of memory occupied by them.
You have already the seen section 8.5 of the draft standard on initialization.
Details about class constructors can be found in section 12.1 Constructors.
Details about class initialization can be found in section 12.6 Initialization.
Basically, whenever you construct a data type in c++, it can happen in one of two ways. You can either be calling a constructor, or you can essentially be copying chunks of memory around. So constructors are not always called.
In C++, there is a notion of primitives. Integers, doubles, pointers, characters, pointers (to anything) are all primitives. Primitives are data types, but they are not classes. All primitives are safe to copy bitwise. When you create or assign primitives, no constructor is called. All that happens is that some assembly code is generated that copies around some bits.
With classes it's a little more complicated; the answer is that usually a constructor is called, but not always. In particular, C++11 has the concept of trivial classes. Trivial classes are classes that satisfy several conditions:
They use the defaults for all the 'special' functions: constructor, destructor, move, copy, assignment.
They don't have virtual functions.
All non static members of the class are trivial classes or primitives.
As far as C++11 is concerned, objects of any class that satisfy this requirement can be treated like chunks of data. When you create such an object, it's constructor will not be called. If you create such an object on the stack (without new), then its destructor will not be called at program termination either, as would normally be called.
Don't take my word for it though. Check out the assembly generated for the code I wrote. You can see that there are two classes, one is trivial and one is not. The non-trivial class has a call to its constructor in the assembly, the trivial one does not.

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.