When is default constructor generated in C++ [duplicate] - c++

This question already has answers here:
Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?
(3 answers)
Closed 2 years ago.
As per "Inside C++ Object Model" a copy constructor is generated (if not declared by the programmer) by the compiler only when at least any one of the below four conditions are true:
When the class contains a member object of a class for which a copy constructor exists (either explicitly declared by the class designer, as in the case of the previous String class, or synthesized by the compiler, as in the case of class Word)
When the class is derived from a base class for which a copy constructor exists (again, either explicitly declared or synthesized)
When the class declares one or more virtual functions
When the class is derived from an inheritance chain in which one or more base classes are virtual
Which means if I have a class with just constructor then copy constructor will not be provided by the compiler.
Lets take an example:
class test
{
test(){}
};
int main()
{
test obj1; //statement 1
test obj2(obj1); //statement 2
}
Above code works fine. Now the problem comes when I add the following lines in class test:
test(const test& rhs) = delete;
"= delete" ensures that copy constructor is not automatically provided. After adding above line I am getting an error for statement 2 which says Use of deleted function test::test(const test&).
My question is: as per "Inside C++ Object Model" I don't need a copy constructor for the above class so when I am explicitly saying not to generate a copy constructor (using delete) why am I getting an error? Since I was expecting that the compiler won't need a copy constructor for the above class.
I am using gcc version 4.6.3.

For class to be copyable, it needs to have a copy constructor. Whether you write your own, or compiler generates one for you, it doesn't matter — it has to be available for test a; test b(a); to be a valid operation.
You explicitly force compiler to delete the copy constructor — this is new version of old "make copy constructor private" trick. It disallows copying. So don't be surprised that you can't copy. Because you told the compiler to not allow it.

The standard word on implicitly generated copy constructors is [class.copy]/7:
If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.
and [class.copy]/13:
A copy/move constructor that is defaulted and not defined as deleted is implicitly defined if it is odr-used (3.2) or when it is explicitly defaulted after its first declaration. [Note:The copy/move constructor is implicitly defined even if the implementation elided its odr-use (3.2, 12.2). —end note] If the implicitly-defined constructor would satisfy the requirements of a constexpr constructor (7.1.5), the implicitly-defined constructor isconstexpr.
So a copy-constructor is still generated for test, and its getting invoked by statement 2. I would believe that "Inside C++ Object Model" is talking about when a copy-constructor isn't trivial.

This line:
test obj2(obj1)
is trying to call the copy constructor.

Related

What is Compiler Generated constructor for abstract class no data members

I'm running a static analysis tool and getting an error because an abstract class, with no data members, has no constructors.
Given an abstract class with no data members:
class My_Interface
{
public:
virtual void interface_function(void) = 0;
};
Are any constructors generated by the compiler?
If a constructor is generated, what would it's content be?
If a constructor is generated, would it be eliminated by an
optimization level?
The rule documentation in the static analysis says:
If you do not write at least one constructor in a class, the compiler will
write a public constructor for you by default. This rule detects if you
do not declare at least one constructor.
The rule documentation references Scott Meyers, "Effective C++: 55 Specific Ways to Improve your Programs and Design", third edition.
My understanding is that the compiler will not generate constructors for the above case.
Edit 1:
This is not a duplicate of many constructor questions because:
This one has no data members.
This is not asking if a constructor is necessary, but what happens
when a constructor is not provided.
This is C++ language.
The compiler at least theoretically synthesizes a constructor even in this case. Even though you can't create an instance of this class, the constructor will be invoked in the process of creating a derived class (that overrides interface_function, so it can be instantiated).
Given that this is basically a pure interface class, the constructor probably won't do anything, so most compilers will probably optimize it out (quite possibly even when you don't tell it to optimize the code).
Are any constructors generated by the compiler?
Yes. Several. First, from [class.ctor]:
A default constructor for a class X is a constructor of class X that either has no parameters or else each
parameter that is not a function parameter pack has a default argument. If there is no user-declared constructor
for class X, a non-explicit 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:
Several bullet points follow, none of which apply. So we have the equivalent of:
My_Interface() = default;
Then, from [class.copy]:
If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy
constructor is defined as deleted; otherwise, it is defined as defaulted (8.4).
So we have:
My_Interface(const My_Interface&) = default;
Also:
If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly
declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.
So we also have:
My_Interface(My_Interface&& ) = default;
If a constructor is generated, what would it's content be?
All three are generated, all three are = default;
If a constructor is generated, would it be eliminated by an optimization level?
None of the three constructors are trivial because My_Interface has a virtual function. As such, at the very least, the vtable will need to be initialized/copied. So something will have to happen, even if there aren't any members to initialize/copy/move.
Q1. Are any constructors generated by the compiler?
Answer: Yes. From the C++11 Standard:
12.1 Constructors
5 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.
I don't see anything in the standard that answers the other two questions. However, in your case, since there is a virtual member function, the default constructor must, at least, set the virtual table of the object.

Default move constructor in a sub class

In C++11, if the base class has defined its own move (copy) constructor (assignment operator), does its subclass need to define its own move (copy) constructor (assignment operator) in where call the base class's corresponding constructor/operator is called explicitly?
Is it a good idea to define the constructor, destructor, move/copy constructor (assignment operator) clearly every time?
struct Base {
Base() {}
Base(Base&& o);
};
struct Sub : public Base {
Sub(Sub&& o) ; // Need I do it explicitly ? If not,what the compiler will do for me
};
The compiler will generate a default move constructor if you don't specify one in the base class (except some cases, e.g. there's a base class with a deleted move constructor) but you should, in any case, call explicitly the base class' one if you have it:
Sub(Sub&& o) : Base(std::move(o))
According to the standard (N3797) 12.8/9 Copying and moving class objects [class.copy]:
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared move assignment operator, and
— X does not have a user-declared destructor.
As such, if your class meets the above requirements then a default move constructor will be implicitly declared for you.
As already being stated, the base-class has no knowledge of any sub-classes. As such, whether you declare a move constructor in one base class has no effect on the implicit generation of a move constructor in its sub-classes.
As far as it concerns whether you should declare explicitly a constructor/destructor etc. of a class, there's this nice article.
No, you don't have. I'll be automatically generated like default/copy constructor.
From this page,
Implicitly-declared move constructor
If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:
there are no user-declared copy constructors
there are no user-declared copy assignment operators
there are no user-declared move assignment operators
there are no user-declared destructors
(until C++14) the implicitly-declared move constructor is not defined as deleted due to conditions detailed in the next section
then the compiler will declare a move constructor as an inline public member of its class with the signature T::T(T&&).
A class can have multiple move constructors, e.g. both T::T(const T&&) and T::T(T&&). If some user-defined move constructors are present, the user may still force the generation of the implicitly declared move constructor with the keyword default.
Your struct Sub has no user-declared copy constructors, copy assignment operators, move assignment operators or destructors.
And,
Trivial move constructor
The move constructor for class T is trivial if all of the following is true:
It is not user-provided (meaning, it is implicitly-defined or defaulted), and if it is defaulted, its signature is the same as implicitly-defined
T has no virtual member functions
T has no virtual base classes
The move constructor selected for every direct base of T is trivial
The move constructor selected for every non-static class type (or array of class type) member of T is trivial
T has no non-static data members of volatile-qualified type
(since C++14)
A trivial move constructor is a constructor that performs the same action as the trivial copy constructor, that is, makes a copy of the object representation as if by std::memmove. All data types compatible with the C language (POD types) are trivially movable.
Implicitly-defined move constructor
If the implicitly-declared move constructor is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler. For union types, the implicitly-defined move constructor copies the object representation (as by std::memmove). For non-union class types (class and struct), the move constructor performs full member-wise move of the object's bases and non-static members, in their initialization order, using direct initialization with an xvalue argument.
The move constructor of Base is not trivial (it's user-defined). So, the implicitly-defined move constructor of Sub will work as "the move constructor performs full member-wise move of the object's bases and non-static members, in their initialization order, using direct initialization with an xvalue argument."

Default constructor of an Empty Class is public. But how?

I have a simple question:
class my
{
};
my ob;
Compiler allows me to create an object which makes sense. And, I am aware that you can't create object where the constructor is private.
To me it looks that, everything inside the class is private but obviously not the default constructor(because it is allowing me to create the object as default constructor should be public). But what confuses me is that there is no public section in the class.
So, does it create a public section only to put a default constructor under it in this case?
Or there is something else going on and my rationale is incorrect?
Also, how are accesses public, private and protected internally organised/tracked when an object is created/accessed?
I got this question as I never created an object of an empty class until now.
If you do not declare any constructor yourself, C++ compilers will always generate a public trivial constructor for you. More than that even, it will also implicitly create a public copy constructor and assignment operator.
From C++11 standard 12.1.5:
If
there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared
as defaulted. An implicitly-declared default constructor is an inline public member of its class.
and 12.8.7, 12.8.11:
If the class definition does not explicitly declare a copy constructor, one is declared implicitly. [...] An implicitly-declared copy [...] constructor is an inline public member of its class.
and finally 12.8.18, 12.8.20, 12.8.22:
If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. [...] If the definition of a class X does not explicitly declare a move assignment operator, one will be implicitly
declared [...]. An implicitly-declared
copy/move assignment operator is an inline public member of its class.
Note that a move assignment operator will only be generated under certain circumstances, which are beyond the scope of this question, see 12.8.20 for more details.
If you want a private constructor you have to declare it yourself:
class my { my() {} };
If you want to prevent the generation of copy constructor or assignment operator you can either declare, but not implement them:
class my { my(my const &); };
Or, since C++11, explicitly delete them:
class my { my(my const &) = delete; };
Yes, the compiler will produce the default constructor and the default copy constructor and default assignment operators as "public" - because anything else would make the class rather useless...
Of course, those constructors would be rather simple - in fact, it can be replaced with "nothing", since constructing an empty class will do nothing.
The compiler generated default constructor (and other operators) are automatically public. If you want the default constructor to be private then you need to specify this yourself my declaring it within a private section of your class.
The concepts of private, protected and public are only relevant to the compiler. They have no meaning and are not tracked at runtime.
The compiler will generate the default constructor as inline public if it is not defined by the user, the relevant section of the C++ draft standard is 12.1/5:
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.
Usually compiler by default generates 4 things at the time of creation of object.
Default constructor
Copy constructor
Copy assignment operator
Destructor
For example:
class First {
First(){} //default constructor
First(const First &){} //copy constructor
First& operator=(const First&){ //Copy assignment operator
return *this;
}
~First(){} //Destructor
}
These are implicitly inline public member, unless there is no user declared constructor.

Can a move constructor be implicit?

Consider the following class:
class A
{
public:
std::string field_a;
std::string field_b;
}
Now consider the following copy construction:
A a1(a2);
The copy construction will adequately copy A despite the lack of of an explicit copy constructor because the copy constructors for std::string will be called by the compiler generated implicit copy constructor.
What I wish to know is, is the same true for move construction?
EDIT: Testing here shows that:
A a2(std::move(a1));
Will actually result in a copy construction, unless the specific move constructor:
A( A && other ) : a(std::move(other.a)) {}
Is defined.
EDIT EDIT
I pinged Stephan T Lavavej and asked him why VC 2012 doesn't seem to follow what draft 12.8 states regarding implicit move constructor generation. He was kind enough to explain:
It's more of a "feature not yet implemented" than a bug. VC currently
implements what I refer to as rvalue references v2.0, where move
ctors/assigns are never implicitly generated and never affect the
implicit generation of copy ctors/assigns. C++11 specifies rvalue
references v3.0, which are the rules you're looking at.
Yes, from the C++11 draft, 12.8:
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared
as defaulted if and only if
X does not have a user-declared copy constructor,
X does not have a user-declared copy assignment operator,
X does not have a user-declared move assignment operator,
X does not have a user-declared destructor, and
the move constructor would not be implicitly defined as deleted.
The last condition is specified with more detail later:
An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:
a variant member with a non-trivial corresponding constructor and X is a union-like class,
a non-static data member of class type M (or array thereof) that cannot be copied/moved because
overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a
function that is deleted or inaccessible from the defaulted constructor,
a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as
applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or
inaccessible from the defaulted constructor,
any direct or virtual base class or non-static data member of a type with a destructor that is deleted
or inaccessible from the defaulted constructor,
for the copy constructor, a non-static data member of rvalue reference type, or
for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.
Plainly speaking, the move constructor will be implicitly declared if:
The class does not have user-declared any of the other special member functions.
The move constructor can be sensibly implemented by moving all its members and bases.
Your class obviously complies with these conditions.
The compiler synthesizes a move constructor if it can and if there is no user-defined copy constructor. The restriction that no move constructor is synthesized if there is copy constructor is intended to avoid breaking existing code. Of course, all members need to be movable. The exact rules are a bit more involved.

I defined a non-copy constructor; will a copy constructor still be implicitly defined?

Can the (implicit)default copy constructor be called for a class that has already user-defined constructor but that is not the copy constructor?
If it is possible then, suppose we define the copy constructor for the class explicitly, now can the (implicit)default constructor be called?
First, let's clarify our vocabulary a bit. A default constructor is a
constructor which can be called without any arguments. A copy
constructor is a constructor which can be called with a single argument
of the same type. Given this, a "default copy constructor" would be a
constructor with a signature something like:
class MyClass
{
public:
static MyClass ourDefaultInstance;
// default copy constructor...
MyClass( MyClass const& other = ourDefaultInstance );
};
Somehow, I don't think that this is what you meant. I think what
you're asking about is an implicitly declared or an implicitly defined
copy constructor; a copy constructor whose declaration or definition is
provided implicitly by the compiler. The compiler will always provide
the declaration unless you provide a declaration of something that can
be considered a copy constructor. Providing other constructors will not
prevent the compiler from implicitly declaring a copy constructor.
This is different from the default constructor—any user defined
constructor will prevent the compiler from implicitly declaring a
default constructor. This means that if you have a user defined copy
constructor, the compiler will not implicitly declare a default
constructor.
The second important point is that you do not call constructors. The
compiler calls them in certain well defined contexts: variable
definition and type conversion, mainly. The compiler can only call
constructors that are declared (including those that are implicitly
declared). So if you have a user defined constructor (copy or
otherwise), and do not define a default constructor, the compiler cannot
call the constructor except in contexts where it has arguments to call
it with.
To summarize what I think your questions are: the compiler will provide
an implicit copy constructor even if the class has other user defined
constructors, provided none of those constructors can be considered copy
constructors. And if you provide a user defined copy constructor, the
compiler will not provide an implicitly declared default copy constructor.
http://www.cplusplus.com/articles/y8hv0pDG/
The default copy constructor exists if you have not defined one. So yes you can call the default copy constructor, if you haven't defined a copy constructor, however if you do define a copy constructor in your class, you will not be able to call the default one.
There is no such thing as a default copy constructor. There are
default constructors and copy constructors and they are different
things.
The implicitly defined copy constructor (which I think is what you
mean by "default copy constructor") will copy non-static members of
class type using their copy constructor, not their default
constructor. The implicitly defined copy constructor is used when you
don't define your own copy constructor.