I was reading this http://en.wikipedia.org/wiki/C%2B%2B0x#Modification_to_the_definition_of_plain_old_data
It mentions trivial default constructor, trivial copy constructor, copy assignment operator, trivial destructor. What is trivial and not trivial?
In simple words a "trivial" special member function literally means a member function that does its job in a very straightforward manner. The "straightforward manner" means different thing for different kinds of special member functions.
For a default constructor and destructor being "trivial" means literally "do nothing at all". For copy-constructor and copy-assignment operator, being "trivial" means literally "be equivalent to simple raw memory copying" (like copy with memcpy).
If you define a constructor yourself, it is considered non-trivial, even if it doesn't do anything, so a trivial constructor must be implicitly defined by the compiler.
In order for a special member function to satisfy the above requirements, the class must have a very simplistic structure, it must not require any hidden initializations when an object is being created or destroyed, or any hidden additional internal manipulations when it is being copied.
For example, if class has virtual functions, it will require some extra hidden initializations when objects of this class are being created (initialize virtual method table and such), so the constructor for this class will not qualify as trivial.
For another example, if a class has virtual base classes, then each object of this class might contain hidden pointers that point to other parts of the very same object. Such a self-referential object cannot be copied by a simple raw memory copy routine (like memcpy). Extra manipulations will be necessary to properly re-initialize the hidden pointers in the copy. For this reason the copy constructor and copy-assignment operator for this class will not qualify as trivial.
For obvious reasons, this requirement is recursive: all subobjects of the class (bases and non-static members) must also have trivial constructors.
A constructor of a class A is trivial if all the following are true:
It is implicitly defined (compiler synthesized)
A has no virtual functions and no virtual base classes
All the direct base classes of A have trivial constructors
The classes of all the nonstatic data members of A have trivial constructors
There are correct answers already, but here is the quote from the Standard (which I was looking for when I came across this post):
(§12.1/5)
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.
This is from C++11. C++03 lacks the second item and uses the phrase implicitly declared instead of not user-provided. It is otherwise identical.
Note that this specification only covers trivial default constructors. The word attribute trivial can also be used in different contexts, e.g. copy constructors.
Related
I've been reading the C++ standard trying to understand if there are any observable differences between trivial, simple, and implicitly defined constructors/assignment operators/destructors. From my current understanding there doesn't seem to be a difference, but that seems odd, why spend so much time defining them when it doesn't matter?
As a particular concrete example, consider copy constructors.
A trivial copy constructor copies all fields and base classes field-by-field if all fields and base classes are trivial.
Otherwise, the implicitly generated copy constructor: "performs full member-wise copies of bases and non-static members in initialization order".
If I understand it correctly, if a class has all trivial bases and fields but has a defaulted copy-constructor, then the defaulted copy-constructor will do exactly the same thing as the trivial constructor. Not even the initialization order seems to be relevant here because the fields are all disjoint (since trivial implies the absence of virtual base classes).
Is there ever an instance when a trivial copy-constructor will do something different than an explicitly defaulted copy constructor?
Generally, the same logic seems to hold for other constructors and destructors as well. The argument for assignment is a little bit more complex due to the potential for data races, but it seems like all of those would be undefined behavior by the standard if the class was actually trivial.
Not exactly about the behavior of the actual special member function per-se*, but consider the following:
struct Normal
{
int a;
};
static_assert(std::is_trivially_move_constructible_v<Normal>);
static_assert(std::is_trivially_copy_constructible_v<Normal>);
static_assert(std::is_copy_constructible_v<Normal>);
This all seems well and good.
Now consider the following:
struct Strange
{
Strange() = default;
Strange(Strange&&) = default;
};
static_assert(std::is_trivially_move_constructible_v<Strange>);
static_assert(!std::is_trivially_copy_constructible_v<Strange>);
static_assert(!std::is_copy_constructible_v<Strange>);
Hmm. The mere act of explicitly defaulting a move constructor disallows the object from being copy constructible!
Why is this?
Because, even though the compiler is still defining the move constructor for Strange, it's still a user-declared move constructor, which disables the generation of the copying special member functions.
The standard is very finicky about which special member functions get generated when you have user-declared versions of them, so it's best to stick with the Rule of Five or Zero.
Live Demo
Extra credit
By explicitly defaulting a default constructor for Strange, it is no longer an aggregate type (whereas Normal is). This opens up a whole different can of worms about initialization.
*Because as far as I know, the behavior of an explicitly defaulted special member function is identical to the trivial version of that function (or rather, it's the other way around). However, I have to note one peculiarity about the standard wording; when discussing the implicitly declared copy constructor, the standard neglects to say "implicitly declared as defaulted" like it does for the default and move constructors. I believe this to be a minor typo.
As a particular concrete example, consider copy constructors.
A trivial copy constructor copies all fields and base classes field-by-field if all fields and base classes are trivial.
Otherwise, the implicitly generated copy constructor: "performs full member-wise copies of bases and non-static members in initialization order".
The Standard specifies the behavior of implicitly defined special functions in just one place each. For example, [class.copy.ctor]/11 defines whether or not a copy or move constructor qualifies as "trivial". [class.copy.ctor]/14, which contains the quote about "performs a memberwise copy/move", applies whether or not the copy or move constructor is "trivial". When paragraph 11 talks about "the constructor selected" to move a base or member, it's referring to the choices made by the (potential) definition described by paragraph 14.
So yes, being trivial doesn't make a difference for how the class object is initialized. Instead, it makes a difference for other uses of an object of that type, sometimes to allow treating the class type in a more "C-like" way. This isn't a complete listing, but some notable Standard rules which reference triviality:
Implicitly declared special member functions of a union or class containing an anonymous union are defined as deleted if the corresponding special member of any class-type variant member is not trivial.
It's valid to copy objects of a trivially copyable class (see [class.prop]/1) byte by byte. ([basic.types]/2-3).
It's always valid to pass an object of class type through a C-style variadic function's ... if the copy constructor, the move constructor (if any), and the destructor are all trivial. Otherwise, passing an object of the class type is conditionally supported. ([expr.call]/12)
Of course, the std::is_trivially_* traits can tell the difference.
Does the presence of a user-defined "Rule of 5" function (destructor, copy constructor, copy-assignment operator, move constructor, or move assignment operator) in a particular class affect whether these functions will get generated in its derived or base classes? If so, in what way?
Put another way, if I'm trying to determine what functions will be implicitly generated for a particular class, do I need information about it's parent or child classes?
Optional Question: Does the presence of one of these functions in a particular class affect the generated code for implicitly generated functions of other classes in the hierarchy? If so, in what way?
The compiler will always declare a destructor for a class C that has no user-declared destructor (C++17 [class.dtor]/4). However, if any base class of C has a deleted or inaccessible constructor, then C's destructor will also be declared as deleted (p5).
A similar statement holds for copy constructors ([class.copy.ctor]/6) and copy assignment operators ([class.copy.assign]/2).
In the case of a move constructor, the compiler will only implicitly declare it for a class C if the user did not declare any Rule of 5 functions for C ([class.copy.ctor]/8). The base classes of C can affect whether the move constructor of C is deleted or not, but they do not affect whether the compiler generates a declaration. A similar statement holds for move assignment operators ([class.copy.assign]/4).
As I knew until today there are four default things create when creating a new class. "Default constructor", "Destructor", "Copy constructor" and "Assignment operator". But today when I was going trough a C++ article, it said that there can be situations where the copy constructor is not create by default.
Is that true?
If it is, in which situations?
In those situations, how can an instance of that class be passed by value?
1) Yes, there can be situations where the copy constructor is not created by default.
2) The conditions where the implicitly declared default constructor is deleted are laid out in 12.8 Copying and moving class objects [class.copy]:
12.8.7 is about how the declaration of other special member functions affect the implicitly declared copy constructor. Whenever the class declares a copy constructor, a move constructor or a move assignment operator. If it declares any one of those, then you don't get an implicitly declared one.
...
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.
12.8.11 is about how the data members and base classes affect the implicitly declared copy constructor. Essentially, if the class has any data members or base classes that are not copyable, the implicitly declared copy constructor is deleted:
11 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
...
3) You can declare and define (either by providing an implementation or defaulting a copy constructor, or a move copy constructor, or both.
Yes, that is correct. For example, if a member of the class is not copyable/assignable (e.g. a member has a private assignment operator and private copy constructor), then you won't be able to rely on a default copy constructor for the containing class. If you want the containing class to be copyable/assignable under those circumstances, then you need to define those operations explicitly.
That being said, in most cases, you should avoid passing by value. In most circumstances, you should be passing an object by constant reference or passing a smart pointer (e.g. std::unique_ptr) of your object. Passing by value (and any code that does an unnecessary amount of copying) will produce less efficient code than cases where you are able to reuse existing implementations. Additionally, for polymorphic objects, pass-by-value causes "slicing" (the functionality is truncated from the runtime type to the declared type to which the object is being copied), and so pass-by-value is particularly dangerous and error-prone when operating with any data types that might possibly be inherited.
Edit
To clarify the above a little bit... in terms of passing by const-reference vs passing by value, the decision should depend on the size of the object and how expensive it is to copy. Boost provides a handy mechanism in "call traits" (call_traits<T>::param_type) to automatically select between a value and a const reference based on the size of an object. When making this decision, it's also useful to distinguish between value types (objects that behave similarly to primitives -- for example, by overloading various operators and that are copyable, assignable, and cannot be inherited) and user-defined polymorphic types. Whenever you have a type that declares a virtual method, as a general rule of thumb, that object should be passed by reference or const reference to avoid the slicing which I mentioned above.
In terms of passing by smart pointer, generally this is done when transferring or sharing ownership (otherwise you should generally just pass around a reference to the object in question).
I actually got the idea of this question when I was discussing on another question of mine (Member not zeroed, a clang++ bug?). That question is about C++11 value-initialization, but when I saw the C++03 value-initialization rule someone posted there, I am confused.
The value-initialization rule from C++03 is:
To value-initialize an object of type T means:
if T is a class type (clause 9) with a user-declared 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 non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is
value-initialized;
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized
Please look at the second bullet which defines the value-initialize process for a type without user-declared constructor. This rule doesn't mention a constructor call. As we can see from the description of other cases of value-initialize or from the description of default-initialize, if constructor should be called, it will be explicitly mentioned in the text of the standard. I know there is certain initialization form that constructor doesn't get called (e.g. {}-initialization for aggregates), but should it be the case for value-initialize of non-union class type without a user-declared constructor? The implicitly declared constructor of such a type could easily be non-trivial. For example:
class A {
public:
virtual void f() {}
};
According to the rule in C++03, if the implicitly declared non-trivial constructor doesn't get called in the process of the value-initialization of an object of A, how does the vptr of the object get setup? (I know things related to vptr is all implementation-defined, but this doesn't change the major point I'm trying to make here.)
(Someone would argue that the absence of mentioning a constructor call in the rule doesn't mean constructor won't get called. OK. Let's say constructor will get called according to some other rule I may have overlooked, but since all members need to be value-initialized anyway, wouldn't that cause the members' constructors to be called more than once?)
Asking a question for C++03 when it's already C++11 everywhere may seem worthless. Yeah, that's a valid point. However, I think I could more or less learn something if I finally figure this out (whether I am wrong and why).
EDIT: Maybe I shouldn't have used vptr as an example. My point is, wouldn't skipping the call to a non-trivial constructor cause some potential problem for the validity of the object? After all, it's called non-trivial for a reason.
As far as the Standard is concerned, the constructor is not responsible for setting up the vtable. There is nothing responsible for setting up the vtable; vtables don't exist, as far as the Standard is concerned.
Rather, the vtable is a consequence of the other rules the compiler has to follow, relating to virtual function binding and such. So whether or not the constructor is called, the vtable's going to be set up somewhere, because otherwise the compiler will have trouble meeting its other obligations. That doesn't contradict the value-initialization rule; rather, it adds nuance to the practicalities of implementing the rule.
When a class X has no user-provided constructor, its default constructor does exactly what a constructor of the form X::X() {} would (C++03[class.ctor]§6). And as far as the standard is concerned, this is defined to perform default initialisation of all members and base class subobjects, and nothing else. So "calling the generated default constructor" is identical to "default-initialising all data members and base class subobjects."
So this actually does "less" than the value initialisation you quoted - as that value initialisation value-initialises all data members and base class subobjects. So it does all the constructor does, and more.
As far as implementation-specific things (like the vtable pointer) go, these are outside of the scope of the standard. It is a compiler's responsibility to make sure all of its implementation-specific mechanisms work regardless of constructor calls mandated by the standard.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why do we not have a virtual constructor?
I know this has been asked before but I didn't understand the complex technical words used in the other answers.
I read on a community the reason that constructors cannot be virtual is
The ‘virtual’ mechanism works on a logically complete (completely constructed) object. We know that we use constructors to logically initialize our objects. In other words, the object is not completely constructed until the constructor has finished executing. Thus, we can’t have virtual constructors.
There is a misconception that by then virtual table is incomplete so we can’t have virtual constructors. Just before the constructor starts executing the virtual table is properly constructed and the ‘this’ pointer passed to the constructors. Moreover, virtual table mechanism is implementation depended, and finds no place in the C++ standard. And hence, to argue over this issue using the virtual table concept is illogical.
Now, as the constructor finishes executing any other function can be virtual. Destructor is no exception to this rule as it is a function. Virtual destructors are required in case we use a base class pointer to refer to a derived class object, use it, and then delete it. If we have virtual destructor, using ‘delete’, a chain of destructors is called starting from the derived to the base. But, had there been no ‘virtual’ in destructor only the base class destructor is called (and not the derived). This (may) generate inconsistencies in the program.
Is the above reason correct? The answer doesn't talk about the static and dynamic types of objects.
Virtual constructors don't make sense and aren't necessary. The only time you call a constructor is when creating an object. You need to know the type of an object in order to create it, so the static and dynamic types are the same, and the correct constructor to call is the one for that type.
That's why they aren't necessary. Why they don't make sense, is that when creating an object, base class constructors are called as well as derived class constructors. If the base class constructor was overridden in the derived class, is that supposed to mean that the base class constructor isn't called after all?
Other languages have virtual constructors, perhaps because constructors in those languages are methods, and they only have virtual invocation for non-static methods. But those other languages (Java and Python spring to mind) have to introduce special rules that constructors must/should construct their base class explicitly as a call from the constructor. C++ just does it (perhaps in an initializer list, if the base class constructor requires parameters), using non-virtual constructors, and there is no option to enter the body of the constructor with uninitialized base class sub objects.
To quote from The C++ Programming Language:
To construct an object, a constructor
needs the exact type of the object it
is to create. Consequently, a
constructor cannot be virtual.
Furthermore, a constructor is not
quite an ordinary function. In
particular, it interacts with memory
management routines in ways ordinary
member functions don’t. Consequently,
you cannot have a pointer to a
constructor.
It must be interesting to note that C++ do have an idiom called virtual constructor. You can read more about that here.
Yes, the reason is you need to have a pointer/reference to a complete object already before you can call a virtual function. When the constructor is being invoked there's no complete object yet. Even more, when you do new SomeClass() you don't even have a pointer yet - the pointer is returned upon the new statement is completed successfully.
The virtual keyword cannot be applied to a constructor since a constructor turns raw bits into a living object, and until there is a living object against which to invoke a member function, the member function cannot possibly work correctly. Instead of thinking of constructors as normal member functions on the object, imagine that they are static member functions that create objects. - C++ FAQs