• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
johnmarinelli

Rule of Three, and const-correctness questions

39 posts in this topic

But sometime it's even not about resources. Do you need to follow the rule of three if your object has a const POD member?

Good point. I recently had to implement copy and assignment operators for a class with reference members. And as you say, you don't need a destructor for that.

Also, i saw the linked article to be more about not needing the rule of three if you use smart pointers/RAII, and not about implementing your own smart pointers.

My point is one should be useing smart pointers with the right copy semantics, or a wrapper that implements copy semantics per resource.
0

Share this post


Link to post
Share on other sites

My point is one should be useing smart pointers with the right copy semantics, or a wrapper that implements copy semantics per resource.

What do you mean by that?
When you copy a smart pointer, the result is another smart pointer. The object to which they point doesn’t change, nor do you need to write different copy semantics for smart pointers of different kinds/different resources.

I think you are confusing copying the smart pointer itself and copying the object to which it points. If you copy a smart pointer you just get another smart pointer—if the object to which it points needs to also be copied it will be by its own copy semantic, not by those of the smart pointer.
If you copy the object to which it points you still have to implement copy semantics for that object if it is complex, regardless of whether or not it is a raw pointer being dereferenced or a smart pointer being dereferenced. This in itself is not related to either Rule of X.

The only thing that is related is that the smart pointer will delete the object to which it points for you automatically, eliminating the need for you to write an explicit destructor.


L. Spiro Edited by L. Spiro
0

Share this post


Link to post
Share on other sites

If you copy a smart pointer you just get another smart pointer—if the object to which it points needs to also be copied it will be by its own copy semantic, not by those of the smart pointer.

Just thought I'd throw a slight spanner in the works there by mentioning value_ptr. smile.png
http://www.mr-edd.co.uk/code/value_ptr
0

Share this post


Link to post
Share on other sites

My point is one should be useing smart pointers with the right copy semantics, or a wrapper that implements copy semantics per resource.

What do you mean by that?
When you copy a smart pointer, the result is another smart pointer. The object to which they point doesn’t change, nor do you need to write different copy semantics for smart pointers of different kinds/different resources.

I think you are confusing copying the smart pointer itself and copying the object to which it points. If you copy a smart pointer you just get another smart pointer—if the object to which it points needs to also be copied it will be by its own copy semantic, not by those of the smart pointer.
If you copy the object to which it points you still have to implement copy semantics for that object if it is complex, regardless of whether or not it is a raw pointer being dereferenced or a smart pointer being dereferenced. This in itself is not related to either Rule of X.

The only thing that is related is that the smart pointer will delete the object to which it points for you automatically, eliminating the need for you to write an explicit destructor.


L. Spiro

If you need to duplicate an object on copy, then you don't need a pointer at all.

 

A single resource should be managed by a single object. If copying the resource duplicates the resource, then that's part of managing the resource. The example of int * as a resource is contrived. Wanting resources to duplicate on copy is a rare. More often, a shared_ptr will implement the right semantics. If no smart pointer exists that does the right thing, then a single class that manges the resource and implements copy semantics is the way to go.

0

Share this post


Link to post
Share on other sites

 

You only need a const qualifier if you're passing by reference/pointer and you don't want the function to change the object being passed.


In addition to documenting your intent, const does have a function in this case -- it prevents you from modifying the argument inside the function body.

 

Very good point. Others have made the argument that it's about documentation. I fail to find that a useful argument. This, on the other hand, does make sense. While I'm personally in the habit of never modifying function arguments myself, I do see the value in this case of helping to identify potential mistakes before they happen.

0

Share this post


Link to post
Share on other sites

First, better post ever.

 

Second, shouldn't this thread be stickied or something. It seems too good to be archived and be forgotten.

 

Three, I take it that Rule of Three, Rule of Two, and RAII are just C++ rules. Or do they apply to languages like C# and Java?

Edited by Alpha_ProgDes
0

Share this post


Link to post
Share on other sites

... shouldn't this thread be stickied or something. It seems too good to be archived and be forgotten.

 

Agreed that there's a lot of good stuff here. It would be nice to have a way of immortalizing things like this somehow without making them sticky; you'd soon enough overrun the front page with stickies. Its a hard problem, actually, to bubble content to the top in an effective way that also scales, even when all the content is curated. We have the same problem on MSDN, where I work. Most places, and most users, rely on search.

 

Arise thread long since dead. Haunt thy forums from which thou were created.

 

Please check the last posting date before you post.

 

Nice image! But the thread is only ~6 months buried, and Leeor was even on-topic. That's only low-level necromancy at best biggrin.png.

0

Share this post


Link to post
Share on other sites

Three, I take it that Rule of Three, Rule of Two, and RAII are just C++ rules. Or do they apply to languages like C# and Java?

The Rules of Two or Three are C++ specific. RAII is a more general principle that may be applied to languages like java and C#, but not as effectively, because those languages don't schedule object destruction predictably.
0

Share this post


Link to post
Share on other sites

The Rule of Three is out-dated and does not play well with exceptions. The Rule of Two is much safer as it relies on RAII, which is in itself (almost) always the correct choice.
Rule of Two

 

 

L. Spiro

 

 

It's worth noting it has become significantly simpler now:

 

The Rule of Zero (which is actually a particular instance of the Single Responsibility Principle):

 

"Classes that have custom destructors, copy/move constructors or copy/move assignment operators should deal exclusively with ownership. Other classes should not have custom destructors, copy/move constructors or copy/move assignment operators."

 

See: http://flamingdangerzone.com/cxx11/2012/08/15/rule-of-zero.html

Edited by Matt-D
0

Share this post


Link to post
Share on other sites

In addition to documenting your intent, const does have a function in this case -- it prevents you from modifying the argument inside the function body.

 
Very good point. Others have made the argument that it's about documentation. I fail to find that a useful argument. This, on the other hand, does make sense. While I'm personally in the habit of never modifying function arguments myself, I do see the value in this case of helping to identify potential mistakes before they happen.

Note that if you want to prevent modification of the function parameters in your function you don't need to put const on the parameters in the header, only in the implementation. The C++ overloading rules make T and const T the same for parameter types. So you can have foo(int a) in the function declaration in the header and foo(const int a) in the function definition. (Barring compiler bugs anyways. I've heard of one compiler that doesn't perform parameter type resolution properly.)
0

Share this post


Link to post
Share on other sites
I looked at L. Spiro's link about the Rule of Two.

I'm confused about a couple of points. What is the purpose of the reset() and swap() functions? Reset deletes the pointer then assigns the incoming pointer to the deleted pointer! O.o How does that work and under what circumstances would I use swap?
1

Share this post


Link to post
Share on other sites

Arise thread long since dead.

 

 I didn't think it was that old... whoops. Besides, I felt the need to respond to a valid counter point to my original argument.

 


Note that if you want to prevent modification of the function parameters in your function you don't need to put const on the parameters in the header, only in the implementation. The C++ overloading rules make T and const T the same for parameter types. So you can have foo(int a) in the function declaration in the header and foo(const int a) in the function definition. (Barring compiler bugs anyways. I've heard of one compiler that doesn't perform parameter type resolution properly.)

 

More good points.

0

Share this post


Link to post
Share on other sites

 

 

In addition to documenting your intent, const does have a function in this case -- it prevents you from modifying the argument inside the function body.

 
Very good point. Others have made the argument that it's about documentation. I fail to find that a useful argument. This, on the other hand, does make sense. While I'm personally in the habit of never modifying function arguments myself, I do see the value in this case of helping to identify potential mistakes before they happen.

 

Note that if you want to prevent modification of the function parameters in your function you don't need to put const on the parameters in the header, only in the implementation. The C++ overloading rules make T and const T the same for parameter types. So you can have foo(int a) in the function declaration in the header and foo(const int a) in the function definition. (Barring compiler bugs anyways. I've heard of one compiler that doesn't perform parameter type resolution properly.)

 

 

Adding to that, this is perfectly fine if the parameter is passed by value -- it doesn't communicate the constraint to the client, but this is fine (maybe even preferable) since it doesn't impact them.

 

But for parameters passed by reference or pointer types, its critical that const appear in the header as well, because then you need to communicate to the client that even though you're taking the parameter by ref or ptr, you are promising not to change it. I don't actually know off-hand, but passing by ref or ptr might affect the overload rules sicrane mentions (that is, are &T and const &T treated differently than T and cont T, WRT overloading), so the point in practice may be moot, enforced by the compiler anyhow. Just be aware that you need to think about how the parameters are passed in this context.

0

Share this post


Link to post
Share on other sites
When a T is a pointer or reference then [tt]const T[/tt] is not the same as adding [tt]const[/tt] to the thing it refers to. Say T is [tt]U *[/tt]. [tt]const T[/tt] is [tt]U * const[/tt], a const pointer to non-const U, not [tt]const U *[/tt], a non-const pointer to const U. So for the purpose of overload resolution [tt]foo(U *)[/tt] and [tt]foo(U * const)[/tt] are the same, but different than [tt]foo(const U *)[/tt].
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0