diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2023-09-08 16:43:06 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2023-09-08 16:43:06 -0400 |
| commit | 08cdf72330276a4b4883fea41c3ada1087800a41 (patch) | |
| tree | c60f14feee3dd40e5d762a17cb8c76ba446d1ab8 /src/dynamic-array.hpp | |
| parent | 9d6c681037eb4fb3c6d9eca6b1ff1d01d429614e (diff) | |
Use move operator for DynArray<T>::Push
The EventBucket struct has a DynArray as a member.
Calling ::Push({}) instantiates a new item and thus a new
DynArray. When the new `{}` object goes out of scope, the DynArray
destructor was being called, invalidating the data pointer.
This commit ensures that if the object is cloned or moved, the
pointer, which now lives in the outer array, remains valid.
Diffstat (limited to 'src/dynamic-array.hpp')
| -rw-r--r-- | src/dynamic-array.hpp | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/dynamic-array.hpp b/src/dynamic-array.hpp index 978e291..f06ddac 100644 --- a/src/dynamic-array.hpp +++ b/src/dynamic-array.hpp @@ -11,7 +11,7 @@ #define BAKE_DYN_ARRAY(T) template struct DynArray<T>; struct DynArrayBase { - char *ptr = nullptr; + mutable char *ptr = nullptr; int64_t elementSize = 0; int64_t elementCount = 0; int64_t reservedCount = 0; @@ -21,6 +21,10 @@ template <typename T> struct DynArray: DynArrayBase { DynArray(); explicit DynArray(int64_t reserveCount); + DynArray(const DynArray<T> &other); + DynArray(DynArray<T> &&other); + DynArray &operator=(const DynArray<T> &other); + DynArray &operator=(DynArray<T> &&other); ~DynArray(); T &operator[](std::size_t index); T *GetPtr(); @@ -50,6 +54,40 @@ template <typename T> inline DynArray<T>::DynArray() { this->elementSize = sizeof(T); } +template <typename T> inline DynArray<T>::DynArray(const DynArray<T> &rh) { + this->ptr = rh.ptr; + this->elementSize = rh.elementSize; + this->elementCount = rh.elementCount; + this->reservedCount = rh.reservedCount; + rh.ptr = nullptr; +} + +template <typename T> inline DynArray<T>::DynArray(DynArray<T> &&rh) { + this->ptr = rh.ptr; + this->elementSize = rh.elementSize; + this->elementCount = rh.elementCount; + this->reservedCount = rh.reservedCount; + rh.ptr = nullptr; +} + +template <typename T> inline DynArray<T> &DynArray<T>::operator=(const DynArray<T> &rh) { + this->ptr = rh.ptr; + this->elementSize = rh.elementSize; + this->elementCount = rh.elementCount; + this->reservedCount = rh.reservedCount; + rh.ptr = nullptr; + return *this; +} + +template <typename T> inline DynArray<T> &DynArray<T>::operator=(DynArray<T> &&rh) { + this->ptr = rh.ptr; + this->elementSize = rh.elementSize; + this->elementCount = rh.elementCount; + this->reservedCount = rh.reservedCount; + rh.ptr = nullptr; + return *this; +} + template <typename T> inline DynArray<T>::~DynArray() { DynArrayDestroy(this); } @@ -81,7 +119,9 @@ template <typename T> inline void DynArray<T>::Push(const T &val) { auto safeReserveCount = this->reservedCount == 0 ? 1 : this->reservedCount; DynArrayReserve(this, int64_t(safeReserveCount * 1.5)); } - std::memcpy(this->ptr + (sizeof(T) * this->elementCount), &val, sizeof(T)); + auto itemPtr = this->ptr + (sizeof(T) * this->elementCount); + auto &targetItem = *reinterpret_cast<T *>(itemPtr); + targetItem = val; this->elementCount += 1; } |
