Possible Duplicate:
What’s the point in defaulting functions in C++11?
C++11 introduced defaulted methods (e.g. void myMethod() = default;
).
What does it do to methods (how do methods behave after being default
ed). How do I use them properly (what are its uses)?
There are a number of class members that are considered "special member functions" by the C++ standard. These are:
These member functions are special in that the language does special things with them on types. Another thing that makes them special is that the compiler can provide definitions for them if you do not. These are the only functions that you can use the = default;
syntax on.
The issue is that the compiler will only provide a definition under certain conditions. That is, there are conditions under which a definition will not be provided.
I won't go over the entire list, but one example is what others have mentioned. If you provide a constructor for a type that is not a special constructor (ie: not one of the constructors mentioned above), a default constructor will not be automatically generated. Therefore, this type:
struct NoDefault
{
NoDefault(float f);
};
NoDefault
cannot be default constructed. Therefore, it cannot be used in any context where default construction is needed. You can't do NoDefault()
to create a temporary. You can't create arrays of NoDefault
(since those are default constructed). You cannot create a std::vector<NoDefault>
and call the sizing constructor without providing a value to copy from, or any other operation that requires that the type be DefaultConstructible
.
However, you could do this:
struct UserDefault
{
UserDefault() {}
UserDefault(float f);
};
That would fix everything, right?
WRONG!
That is not the same thing as this:
struct StdDefault
{
StdDefault() = default;
StdDefault(float f);
};
Why? Because StdDefault
is a trivial type. What does that mean? I won't explain the whole thing, but go here for the details. Making types trivial is often a useful feature to have, when you can do it.
One of the requirements of a trivial type is that it does not have a user-provided default constructor. UserDefault
has a provided one, even though it does the exact same thing as the compiler-generated one would. Therefore, UserDefault
is not trivial. StdDefault
is a trivial type because = default
syntax means that the compiler will generate it. So it's not user-provided.
The = default
syntax tells the compiler, "generate this function anyway, even if you normally wouldn't." This is important to ensure that a class is a trivial type, since you cannot actually implement special members the way the compiler can. It allows you to force the compiler to generate the function even when it wouldn't.
This is very useful in many circumstances. For example:
class UniqueThing
{
public:
UniqueThing() : m_ptr(new SomeType()) {}
UniqueThing(const UniqueThing &ptr) : m_ptr(new SomeType(*ptr)) {}
UniqueThing &operator =(const UniqueThing &ptr)
{
m_ptr.reset(new SomeType(*ptr)); return *this;
}
private:
std::unique_ptr<SomeType> m_ptr;
};
We must write every one of these functions to make the class copy the contents of the unique_ptr; there's no way to avoid that. But we also want this to be moveable, and the move constructor/assignment operators won't automatically be generated for us. It'd silly to re-implement them (and error-prone if we add more members), so we can use the = default
syntax:
class UniqueThing
{
public:
UniqueThing() : m_ptr(new SomeType()) {}
UniqueThing(const UniqueThing &ptr) : m_ptr(new SomeType(*ptr)) {}
UniqueThing(UniqueThing &&ptr) = default;
UniqueThing &operator =(const UniqueThing &ptr)
{
m_ptr.reset(new SomeType(*ptr)); return *this;
}
UniqueThing &operator =(UniqueThing &&ptr) = default;
private:
std::unique_ptr<SomeType> m_ptr;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With