From 7808a52121daa9325021cf6d23c9fc49876acbd0 Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Sat, 30 Sep 2023 03:09:47 -0700 Subject: [PATCH] Entity: Add placement new For the case where the component may already exist, use a placement new to construct the component again, it would be constructed again, but would not need to go through the allocator. --- dGame/Entity.h | 4 ++++ .../dComponentsTests/DestroyableComponentTests.cpp | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/dGame/Entity.h b/dGame/Entity.h index b0b38b2a1..251bac888 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -523,6 +523,10 @@ inline ComponentType* Entity::AddComponent(VaArgs... args) { // If it doesn't exist, create it and forward the arguments to the constructor if (!componentToReturn) { componentToReturn = new ComponentType(this, std::forward(args)...); + } else { + // In this case the block is already allocated and ready for use + // so we use a placement new to construct the component again as was requested by the caller. + new(componentToReturn) ComponentType(this, std::forward(args)...); } // Finally return the created or already existing component. diff --git a/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp b/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp index a89808a90..acb903520 100644 --- a/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp +++ b/tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp @@ -36,6 +36,14 @@ class DestroyableTest : public GameDependenciesTest { } }; +TEST_F(DestroyableTest, PlacementNewAddComponentTest) { + ASSERT_NE(destroyableComponent, nullptr); + ASSERT_EQ(destroyableComponent->GetArmor(), 7); + baseEntity->AddComponent(); + ASSERT_NE(baseEntity->GetComponent(), nullptr); + ASSERT_EQ(destroyableComponent->GetArmor(), 0); +} + /** * Test Construction of a DestroyableComponent */