mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2024-03-22 13:30:58 +08:00
Closes #1119
Make C.43 crisper -- the guideline is that default construction is required for copyable types. A lot of the existing examples then just fall out, without having to be presented as special cases. This was the original intent and I think this new text helps make that clearer.
This commit is contained in:
parent
d9f3149e11
commit
10c0a8b156
|
@ -4409,7 +4409,7 @@ Constructor rules:
|
||||||
* [C.40: Define a constructor if a class has an invariant](#Rc-ctor)
|
* [C.40: Define a constructor if a class has an invariant](#Rc-ctor)
|
||||||
* [C.41: A constructor should create a fully initialized object](#Rc-complete)
|
* [C.41: A constructor should create a fully initialized object](#Rc-complete)
|
||||||
* [C.42: If a constructor cannot construct a valid object, throw an exception](#Rc-throw)
|
* [C.42: If a constructor cannot construct a valid object, throw an exception](#Rc-throw)
|
||||||
* [C.43: Ensure that a value type class has a default constructor](#Rc-default0)
|
* [C.43: Ensure that a copyable (value type) class has a default constructor](#Rc-default0)
|
||||||
* [C.44: Prefer default constructors to be simple and non-throwing](#Rc-default00)
|
* [C.44: Prefer default constructors to be simple and non-throwing](#Rc-default00)
|
||||||
* [C.45: Don't define a default constructor that only initializes data members; use member initializers instead](#Rc-default)
|
* [C.45: Don't define a default constructor that only initializes data members; use member initializers instead](#Rc-default)
|
||||||
* [C.46: By default, declare single-argument constructors `explicit`](#Rc-explicit)
|
* [C.46: By default, declare single-argument constructors `explicit`](#Rc-explicit)
|
||||||
|
@ -5096,17 +5096,16 @@ Another reason has been to delay initialization until an object is needed; the s
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
### <a name="Rc-default0"></a>C.43: Ensure that a value type class has a default constructor
|
### <a name="Rc-default0"></a>C.43: Ensure that a copyable (value type) class has a default constructor
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
Many language and library facilities rely on default constructors to initialize their elements, e.g. `T a[10]` and `std::vector<T> v(10)`.
|
Many language and library facilities rely on default constructors to initialize their elements, e.g. `T a[10]` and `std::vector<T> v(10)`.
|
||||||
A default constructor often simplifies the task of defining a suitable [moved-from state](#???).
|
A default constructor often simplifies the task of defining a suitable [moved-from state](#???) for a type that is also copyable.
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
We have not (yet) formally defined [value type](#SS-concrete), but think of it as a class that behaves much as an `int`:
|
A [value type](#SS-concrete) is a class that is copyable (and usually also comparable).
|
||||||
it can be copied using `=` and usually compared using `==`.
|
|
||||||
It is closely related to the notion of Regular type from [EoP](http://elementsofprogramming.com/) and [the Palo Alto TR](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf).
|
It is closely related to the notion of Regular type from [EoP](http://elementsofprogramming.com/) and [the Palo Alto TR](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf).
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
@ -5178,41 +5177,47 @@ Assuming that you want initialization, an explicit default initialization can he
|
||||||
int i {}; // default initialize (to 0)
|
int i {}; // default initialize (to 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
##### Example
|
##### Notes
|
||||||
|
|
||||||
There are classes that simply don't have a reasonable default.
|
Classes that don't have a reasonable default construction are usually not copyable either, so they don't fall under this guideline.
|
||||||
|
|
||||||
A class designed to be useful only as a base does not need a default constructor because it cannot be constructed by itself:
|
For example, a base class is not a value type (base classes should not be copyable) and so does not necessarily need a default constructor:
|
||||||
|
|
||||||
struct Shape { // pure interface: all members are pure virtual functions
|
// Shape is an abstract base class, not a copyable value type.
|
||||||
void draw() = 0;
|
// It may or may not need a default constructor.
|
||||||
void rotate(int) = 0;
|
struct Shape {
|
||||||
|
virtual void draw() = 0;
|
||||||
|
virtual void rotate(int) = 0;
|
||||||
|
// =delete copy/move functions
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
|
|
||||||
A class that must acquire a resource during construction:
|
A class that must acquire a caller-provided resource during construction often cannot have a default constructor, but it does not fall under this guideline because such a class is usually not copyable anyway:
|
||||||
|
|
||||||
|
// std::lock_guard is not a copyable value type.
|
||||||
|
// It does not have a default constructor.
|
||||||
lock_guard g {mx}; // guard the mutex mx
|
lock_guard g {mx}; // guard the mutex mx
|
||||||
lock_guard g2; // error: guarding nothing
|
lock_guard g2; // error: guarding nothing
|
||||||
|
|
||||||
##### Note
|
|
||||||
|
|
||||||
A class that has a "special state" that must be handled separately from other states by member functions or users causes extra work
|
A class that has a "special state" that must be handled separately from other states by member functions or users causes extra work
|
||||||
(and most likely more errors). For example
|
(and most likely more errors). Such a type can naturally use the special state as a default constructed value, whether or not it is copyable:
|
||||||
|
|
||||||
|
// std::ofstream is not a copyable value type.
|
||||||
|
// It does happen to have a default constructor
|
||||||
|
// that goes along with a special "not open" state.
|
||||||
ofstream out {"Foobar"};
|
ofstream out {"Foobar"};
|
||||||
// ...
|
// ...
|
||||||
out << log(time, transaction);
|
out << log(time, transaction);
|
||||||
|
|
||||||
If `Foobar` couldn't be opened for writing and `out` wasn't set to throw exceptions upon errors, the output operations become no-ops.
|
Similar special-state types that are copyable, such as copyable smart pointers that have the special state "==nullptr", should use the special state as their default constructed value.
|
||||||
The implementation must take care of that case, and users must remember to test for success.
|
|
||||||
|
|
||||||
Pointers, even smart pointers, that can point to nothing (null pointers) are an example of this.
|
However, it is preferable to have a default constructor default to a meaningful state such as `std::string`s `""` and `std::vector`s `{}`.
|
||||||
Having a default constructor is not a panacea; ideally it defaults to a meaningful state such as `std::string`s `""` and `std::vector`s `{}`.
|
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
* Flag classes that are copyable by `=` or comparable with `==` without a default constructor
|
* Flag classes that are copyable by `=` without a default constructor
|
||||||
|
* Flag classes that are comparable with `==` but not copyable
|
||||||
|
|
||||||
|
|
||||||
### <a name="Rc-default00"></a>C.44: Prefer default constructors to be simple and non-throwing
|
### <a name="Rc-default00"></a>C.44: Prefer default constructors to be simple and non-throwing
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user