- Document limitation of TArray and silence warnings about non-trivial types being trivially moved

This commit is contained in:
Braden Obrzut 2019-09-29 21:01:47 -04:00 committed by Christoph Oelckers
parent ff9715c080
commit 63f2bf7ae3
1 changed files with 20 additions and 3 deletions

View File

@ -31,6 +31,20 @@
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
** NOTE: TArray takes advantage of the assumption that the contained type is
** able to be trivially moved. The definition of trivially movable by the C++
** standard is more strict than the actual set of types that can be moved with
** memmove. For example, FString uses non-trivial constructors/destructor in
** order to maintain the reference count, but can be "safely" by passed if the
** opaque destructor call is avoided. Similarly types like TArray itself which
** only null the owning pointers when moving which can be skipped if the
** destructor is not called.
**
** It is possible that with LTO TArray could be made safe for non-trivial types,
** but we don't wish to rely on LTO to reach expected performance. The set of
** types which can not be contained by TArray as a result of this choice is
** actually extremely small.
**
*/
@ -352,7 +366,8 @@ public:
Array[index].~T();
if (index < --Count)
{
memmove (&Array[index], &Array[index+1], sizeof(T)*(Count - index));
// Cast to void to assume trivial move
memmove ((void*)&Array[index], (const void*)&Array[index+1], sizeof(T)*(Count - index));
}
}
}
@ -372,7 +387,8 @@ public:
Count -= deletecount;
if (index < Count)
{
memmove (&Array[index], &Array[index+deletecount], sizeof(T)*(Count - index));
// Cast to void to assume trivial move
memmove ((void*)&Array[index], (const void*)&Array[index+deletecount], sizeof(T)*(Count - index));
}
}
}
@ -394,7 +410,8 @@ public:
Resize (Count + 1);
// Now move items from the index and onward out of the way
memmove (&Array[index+1], &Array[index], sizeof(T)*(Count - index - 1));
// Cast to void to assume trivial move
memmove ((void*)&Array[index+1], (const void*)&Array[index], sizeof(T)*(Count - index - 1));
// And put the new element in
::new ((void *)&Array[index]) T(item);