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.
Related
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.
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.
If I try to compile this code
struct A {
const int j;
};
A a;
I'll get an expected error:
error: uninitialized const member in ‘struct A’
but, if I try to compile this one:
struct A {
const int j;
};
A * a = new A();
I'll get a successful build.
The question is: why does new allocation allows creating a variable with const member without explicit constructor and stack allocation - doesn't ?
It's not because of the heap allocation, but because of the parenthesis you use when allocating. If you do e.g.
A* a = new A;
it would also fail.
The reason it works when you add the parenthesis is because then your structure is value initialized, and for a POD-type like A value-initialization value-initializes each member, and the default value-initialization for int is zero.
That means it would probably work creating the variable on the stack as well, if you just add the value-initialization parenthesis:
A a = A(); // watch out for the http://en.wikipedia.org/wiki/Most_vexing_parse
Though that brings other potential problems, better use uniform initialization if you can (requies C++11):
A a{};
This is ill-formed as of C++14. §12.1 [class.ctor] says that
4 A defaulted default constructor for class X is defined as deleted
if:
[...]
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,
[...]
A default constructor is trivial if it is not user-provided and if:
its class has no virtual functions (10.3) and no virtual base classes (10.1), and
no non-static data member of its class has a brace-or-equal-initializer, and
all the direct base classes of its class have trivial default constructors, and
for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default
constructor.
§8.5 [dcl.init] says in turn that
7 To default-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9), the default constructor (12.1) for T is called (and the initialization is
ill-formed if T has no default constructor or overload resolution
(13.3) results in an ambiguity or in a function that is deleted or
inaccessible from the context of the initialization);
[...]
8 To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9) with either no default constructor (12.1) or a default constructor that is
user-provided or deleted, then the object is default-initialized;
[...]
The empty pair of parentheses results in value-initialization. The default constructor for A is defined as deleted per [class.ctor]/p4. Thus, by [dcl.init]/p8, value-initialization means default-initialization, and by p7 the initialization is ill-formed because the constructor is deleted.
The C++11 version actually allowed value-initialization in this context; it says for value-initialization that, among other things,
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.
Since by the definition above the default constructor is trivial (even though it is deleted), it is not actually called. This was considered a defect in the standard and the relevant wording was changed by CWG issue 1301.
Compiler vendors usually do implement defect resolutions, so this could be considered a bug in GCC 4.8 that's been fixed in 4.9.
Related: How to initialize a non-POD member in Union
The standard says
At most one non-static data member of a union may have a brace-or-equal-initializer.
But
struct Point {
Point() {}
Point(int x, int y): x_(x), y_(y) {}
int x_, y_;
};
union U {
int z;
double w;
Point p = Point(1,2);
};
#include <iostream>
int main () {
U u;
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
}
prints 4196960:0 instead of the expected 1:2.
I consider this a compiler bug. Is that so?
C++11 [class.ctor]/5 states:
A default constructor for a class X is a constructor of class X that can be called without an argument. If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted (8.4). 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.
A default constructor is trivial if it is not user-provided and if:
its class has no virtual functions (10.3) and no virtual base classes (10.1), and
no non-static data member of its class has a brace-or-equal-initializer, and
all the direct base classes of its class have trivial default constructors, and
for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default constructor.
Otherwise, the default constructor is non-trivial.
Since the struct Point in the OP has a non-trivial default constructor,
Point() {}
a defaulted default constructor for a union containing a member of type Point should be defined as deleted according to the first bullet:
X is a union-like class that has a variant member with a non-trivial default constructor
resulting in the program presented in the OP being ill-formed.
However, the committee seems to consider this to be a defect in the case that a member of a union has a brace-or-equal-initializer, per core working group issue 1623:
According to 12.1 [class.ctor] paragraph 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,
...
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),
...
Because the presence of a non-static data member initializer is the moral equivalent of a mem-initializer, these rules should probably be modified not to define the generated constructor as deleted when a union member has a non-static data member initializer. (Note the non-normative references in 9.5 [class.union] paragraphs 2-3 and 7.1.6.1 [dcl.type.cv] paragraph 2 that would also need to be updated if this restriction is changed.)
It would also be helpful to add a requirement to 9.5 [class.union] requiring either a non-static data member initializer or a user-provided constructor if all the members of the union have const-qualified types.
On a more general note, why is the default constructor defined as deleted just because a member has a non-trivial default constructor? The union itself doesn't know which member is the active one, and default construction won't initialize any members (assuming no brace-or-equal-initializer). It is up to the “owner” of the union to control the lifetime of the active member (if any), and requiring a user-provided constructor is forcing a design pattern that doesn't make sense. Along the same lines, why is the default destructor defined as deleted just because a member has a non-trivial destructor? I would agree with this restriction if it only applied when the union also has a user-provided constructor.
Issue 1623 has the status "drafting," indicating that the committee believes the issue is probably a defect - why else allow a brace-or-equal-initializer for a union member? - but hasn't yet devoted the time to determine the proper wording for a resolution. Indeed, the paragraph is largely the same in the current C++14 draft N3936 ([class.ctor]/4), except that the wording "any direct or virtual base class or non-static data member" is everywhere replaced by the simpler "any potentially constructed subobject."
Although the behavior of both compilers is not strictly conforming, I would consider Clang to be behaving in the spirit of the standard. It would appear that GCC becomes confused by the combination of deleted default constructor and brace-or-equal-initializer:
it does diagnose the program as ill-formed in the absence of the brace-or-equal-initializer,
with the brace-or-equal-initializer present and maximum warnings GCC 4.8.2 performs no initialization of the union at all, and even warns that the members are used uninitialized:
main.cpp: In function 'int main()':
main.cpp:17:39: warning: 'u.U::p.Point::y_' is used uninitialized in this function [-Wuninitialized]
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
^
main.cpp:17:22: warning: 'u.U::p.Point::x_' is used uninitialized in this function [-Wuninitialized]
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
^
GCC should probably either conform to the standard and diagnose the program as ill-formed, or emulate clang's behavior and generate a proper constructor from the brace-or-equal-initializer.
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.