Note that there are some explanatory texts on larger screens.

plurals
  1. POC++ composite reference to owner is corrupted when owner is moved
    primarykey
    data
    text
    <p>I've been working at this all day so I hope I don't forget any important details, but here goes. My original goal was to have a player factory that encapsulated the logic of how to create a player. </p> <p>Here's what that looks like:</p> <pre><code>Player PlayerFactory::CreatePlayer() { Player constructee(id_generator++); // c++1x move semantics says this isn't a copy! return constructee; } </code></pre> <p>Within the player, there is a composite PlayerInputComponent member variable. This PlayerInputComponent object encapsulates the logic of dealing with player input, to do this it needs a reference/pointer to the actual player itself. Easy enough, it takes the reference to the player in as it's only parameter to it's constructor.</p> <p>When the player object is constructed, it's initializer list passes a reference to itself to the PlayerInputComponent object. Here's how it looks:</p> <pre><code>Player::Player(const unsigned int id) : id(id), input_component(*this) { ... } </code></pre> <p>I understand that de-referencing this within an initializer list is usually a bad idea, but I'm just using it to set a reference within the PlayerInputComponent object. Here's the constructor:</p> <pre><code>PlayerInputComponent::PlayerInputComponent(Player &amp;player) : player_entity(player) { // set the reference, it is never used within the constructor body } </code></pre> <p>For whatever reason, when the player factory returns the local copy of the player it has created, the references get garbled. My intent, was for the instance of the player created on the stack to be moved and assigned to the callee. This looks like the following:</p> <pre><code>auto player = player_factory.CreatePlayer(); </code></pre> <p>After the code executes the player's composite PlayerInputComponent object's reference to it's player is mangled. I understand that the move constructor for the player is invoked when the factory returns the local player object to the callee, but what happens the reference of the player within the PlayerInputComponent? Is there a better way to solve this problem? I like the semantic meaning of having a reference vs a pointer in this situation, although I did try it with a pointer and get the same thing.</p> <p>Can anyone explain to me what is happening to the PlayerInputComponent's reference to the player when the player object is moved out of the CreatePlayer() member function and assigned to "auto player"?</p> <p>For completeness here are the object's declarations:</p> <pre><code>class PlayerInputComponent { private: Player &amp;player_entity; void HandleKeyboardInput(); public: //PlayerInputComponent(PlayerInputComponent &amp;&amp;other); //PlayerInputComponent(const PlayerInputComponent &amp;other); PlayerInputComponent(Player &amp;player); void Update(); }; </code></pre> <p>And here is the Player:</p> <pre><code>class Player : public Entity{ friend class PlayerFactory; private: const unsigned int id; public: Player(const unsigned int id); // components PlayerInputComponent input_component; }; </code></pre> <p>I've reconstructed a small example below that shows the exact behavior, which compiles/demonstrates the problem. Thank you!</p> <pre><code>class B; class A { public: A(B&amp; bb) : b(bb) { } private: B &amp;b; }; class B { public: B() : a(*this) { othercrap = othercrap2 = 0; } int othercrap; int othercrap2; private: A a; }; class BFactory { public: B CreateB() { B temp; return temp; }; }; B start() { BFactory fac; auto bi = fac.CreateB(); return bi; } int main(int argc, char *argv[]) { auto i = start(); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload