Jump to content
  • Advertisement
Sign in to follow this  
TheComet

The Copy&Swap Idiom

This topic is 2161 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is this not how it's done traditionally? Or am I missing something?


'traditional' isn't a technical term, but in this context it would mean 'plainly wrong and rather straw-mannish'. Of course you can get leakage if you do it that way. You're using raw pointers for resource control. That doesn't mean that C&S is the only alternative. Doing it right is another alternative, as I showed in the block after that.

C&S collects the copying behavior and then adopts it in a single transaction. That's the correct pattern, but C&S is not the only way to implement that pattern, and it can be unclear, make the machine do more work than it needs to, and/or trigger side-effects.

Using smart pointers or other RAII implementors allows you to prepare the new state, and then once everything is created successfully you adopt it. That's the 'normal' way of writing exception safe code. C&S is just a trick for doing that by invoking the copy ctor and then adopting it only if construction succeeds.

 

It does not magically guarantee exception safety.
 

Your code here is NOT exception safe!

    // copy constructor
    Player( const Player& that ) : m_Texture( new Texture(*that.m_Texture) ),
                                                  m_Sprite( new Sprite(*that.m_Texture) ),
                                                  m_Health( new m_HealthController(*that.m_Health) )

    {
    }

What if the allocation for m_Health fails? m_Texture and m_Sprite have already been allocated! How will you reach them in order to release them, since the object failed construction?

Share this post


Link to post
Share on other sites
Advertisement

Your code here is NOT exception safe!

    // copy constructor
    Player( const Player& that ) : m_Texture( new Texture(*that.m_Texture) ),
                                                  m_Sprite( new Sprite(*that.m_Texture) ),
                                                  m_Health( new m_HealthController(*that.m_Health) )

    {
    }
What if the allocation for m_Health fails? m_Texture and m_Sprite have already been allocated! How will you reach them in order to release them, since the object failed construction?

Code like this shows why RAII works best when there is only one resource per object. If you wrap each of m_Texture, m_Sprite, and m_Health in it own object, then these sorts of problems go away. Alternatively, proper use of smart pointers used together with make_shared and the like resolves the problems too, because of how make_shared works.

Not that it's not possible to write a class that maintains two resources and is exception safe, but that's doing things the hard way, and is a likely spot for bugs introduced when the code is later maintained.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!