diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md
index b5c2349..5e54a54 100644
--- a/CppCoreGuidelines.md
+++ b/CppCoreGuidelines.md
@@ -4512,6 +4512,7 @@ Other default operations rules:
* [C.86: Make `==` symmetric with respect of operand types and `noexcept`](#Rc-eq)
* [C.87: Beware of `==` on base classes](#Rc-eq-base)
* [C.89: Make a `hash` `noexcept`](#Rc-hash)
+* [C.90: Rely on constructors and assignment operators, not memset and memcpy](#Rc-memset)
## C.defop: Default Operations
@@ -6539,6 +6540,37 @@ That tends to work better than "cleverness" for non-specialists.
* Flag throwing `hash`es.
+### 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 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));
+ }
+
+
## 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.
@@ -18904,7 +18936,7 @@ Doing so takes away an `#include`r's ability to effectively disambiguate and to
##### Note
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.
##### Enforcement
@@ -20087,12 +20119,12 @@ and errors (when we didn't deal correctly with semi-constructed objects consiste
my = y;
data = nullptr;
}
-
+
~Picture()
{
Cleanup();
}
-
+
bool Init()
{
// 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));
return data != nullptr;
}
-
+
void Cleanup()
{
if (data) free(data);
data = nullptr;
}
};
-
+
Picture picture(100, 0); // not ready-to-use picture here
// this will fail..
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 my;
vector data;
-
+
static size_t check_size(size_t s)
{
// invariant check
Expects(s > 0);
return s;
}
-
+
public:
// even more better would be a class for a 2D Size as one single parameter
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)
};
-
+
Picture picture1(100, 100);
// picture is ready-to-use here...
-
+
// not a valid size for y,
// default contract violation behavior will call std::terminate then
Picture picture2(100, 0);
diff --git a/scripts/hunspell/isocpp.dic b/scripts/hunspell/isocpp.dic
index f5a9c18..80b7d54 100644
--- a/scripts/hunspell/isocpp.dic
+++ b/scripts/hunspell/isocpp.dic
@@ -301,6 +301,7 @@ md
memberinit
members'
memcmp
+memcpy
memmove
memoization
memoized