mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2024-03-22 13:30:58 +08:00
Address items called out in Issue 1424 (#1539)
* Address items called out in Issue 1424 * Fix issues caught by CI * Updates based on PR review
This commit is contained in:
parent
fc32070096
commit
39b9ebdf86
|
@ -4512,6 +4512,7 @@ Other default operations rules:
|
||||||
* [C.86: Make `==` symmetric with respect of operand types and `noexcept`](#Rc-eq)
|
* [C.86: Make `==` symmetric with respect of operand types and `noexcept`](#Rc-eq)
|
||||||
* [C.87: Beware of `==` on base classes](#Rc-eq-base)
|
* [C.87: Beware of `==` on base classes](#Rc-eq-base)
|
||||||
* [C.89: Make a `hash` `noexcept`](#Rc-hash)
|
* [C.89: Make a `hash` `noexcept`](#Rc-hash)
|
||||||
|
* [C.90: Rely on constructors and assignment operators, not memset and memcpy](#Rc-memset)
|
||||||
|
|
||||||
## <a name="SS-defop"></a>C.defop: Default Operations
|
## <a name="SS-defop"></a>C.defop: Default Operations
|
||||||
|
|
||||||
|
@ -6539,6 +6540,37 @@ That tends to work better than "cleverness" for non-specialists.
|
||||||
|
|
||||||
* Flag throwing `hash`es.
|
* Flag throwing `hash`es.
|
||||||
|
|
||||||
|
### <a name="Rc-memset"></a>C.90: Rely on constructors and assignment operators, not `memset` and `memcpy`
|
||||||
|
|
||||||
|
##### Reason
|
||||||
|
|
||||||
|
The standard C++ mechanism to construct an instance of a type is to call its constructor. As specified in guideline [C.41](#Rc-complete): a constructor should create a fully initialized object. No additional initialization, such as by `memcpy`, should be required.
|
||||||
|
A type will provide a copy constructor and/or copy assignment operator to appropriately make a copy of the class, preserving the type's invariants. Using memcpy to copy a non-trivially copyable type has undefined behavior. Frequently this results in slicing, or data corruption.
|
||||||
|
|
||||||
|
##### Example, bad
|
||||||
|
|
||||||
|
struct base
|
||||||
|
{
|
||||||
|
virtual void update() = 0;
|
||||||
|
std::shared_ptr<int> sp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct derived : public base
|
||||||
|
{
|
||||||
|
void update() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void init(derived& a)
|
||||||
|
{
|
||||||
|
memset(&a, 0, sizeof(derived));
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy(derived& a, derived& b)
|
||||||
|
{
|
||||||
|
memcpy(&a, &b, sizeof(derived));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
## <a name="SS-containers"></a>C.con: Containers and other resource handles
|
## <a name="SS-containers"></a>C.con: Containers and other resource handles
|
||||||
|
|
||||||
A container is an object holding a sequence of objects of some type; `std::vector` is the archetypical container.
|
A container is an object holding a sequence of objects of some type; `std::vector` is the archetypical container.
|
||||||
|
@ -18904,7 +18936,7 @@ Doing so takes away an `#include`r's ability to effectively disambiguate and to
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
An exception is `using namespace std::literals;`. This is necessary to use string literals
|
An exception is `using namespace std::literals;`. This is necessary to use string literals
|
||||||
in header files and given [the rules](http://eel.is/c++draft/over.literal) - users are required
|
in header files and given [the rules](http://eel.is/c++draft/over.literal) - users are required
|
||||||
to name their own UDLs `operator""_x` - they will not collide with the standard library.
|
to name their own UDLs `operator""_x` - they will not collide with the standard library.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
@ -20087,12 +20119,12 @@ and errors (when we didn't deal correctly with semi-constructed objects consiste
|
||||||
my = y;
|
my = y;
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Picture()
|
~Picture()
|
||||||
{
|
{
|
||||||
Cleanup();
|
Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
// invariant checks
|
// invariant checks
|
||||||
|
@ -20105,14 +20137,14 @@ and errors (when we didn't deal correctly with semi-constructed objects consiste
|
||||||
data = (char*) malloc(mx*my*sizeof(int));
|
data = (char*) malloc(mx*my*sizeof(int));
|
||||||
return data != nullptr;
|
return data != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cleanup()
|
void Cleanup()
|
||||||
{
|
{
|
||||||
if (data) free(data);
|
if (data) free(data);
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Picture picture(100, 0); // not ready-to-use picture here
|
Picture picture(100, 0); // not ready-to-use picture here
|
||||||
// this will fail..
|
// this will fail..
|
||||||
if (!picture.Init()) {
|
if (!picture.Init()) {
|
||||||
|
@ -20127,14 +20159,14 @@ and errors (when we didn't deal correctly with semi-constructed objects consiste
|
||||||
size_t mx;
|
size_t mx;
|
||||||
size_t my;
|
size_t my;
|
||||||
vector<char> data;
|
vector<char> data;
|
||||||
|
|
||||||
static size_t check_size(size_t s)
|
static size_t check_size(size_t s)
|
||||||
{
|
{
|
||||||
// invariant check
|
// invariant check
|
||||||
Expects(s > 0);
|
Expects(s > 0);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// even more better would be a class for a 2D Size as one single parameter
|
// even more better would be a class for a 2D Size as one single parameter
|
||||||
Picture(size_t x, size_t y)
|
Picture(size_t x, size_t y)
|
||||||
|
@ -20147,10 +20179,10 @@ and errors (when we didn't deal correctly with semi-constructed objects consiste
|
||||||
}
|
}
|
||||||
// compiler generated dtor does the job. (also see C.21)
|
// compiler generated dtor does the job. (also see C.21)
|
||||||
};
|
};
|
||||||
|
|
||||||
Picture picture1(100, 100);
|
Picture picture1(100, 100);
|
||||||
// picture is ready-to-use here...
|
// picture is ready-to-use here...
|
||||||
|
|
||||||
// not a valid size for y,
|
// not a valid size for y,
|
||||||
// default contract violation behavior will call std::terminate then
|
// default contract violation behavior will call std::terminate then
|
||||||
Picture picture2(100, 0);
|
Picture picture2(100, 0);
|
||||||
|
|
|
@ -301,6 +301,7 @@ md
|
||||||
memberinit
|
memberinit
|
||||||
members'
|
members'
|
||||||
memcmp
|
memcmp
|
||||||
|
memcpy
|
||||||
memmove
|
memmove
|
||||||
memoization
|
memoization
|
||||||
memoized
|
memoized
|
||||||
|
|
Loading…
Reference in New Issue
Block a user