Rule of Three, and const-correctness questions

Started by
38 comments, last by SiCrane 10 years, 8 months ago

20101115002739_181_necropost.png

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
Advertisement

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?

Beginner in Game Development?  Read here. And read here.

 

... 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.

throw table_exception("(? ???)? ? ???");

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.

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

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.)
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?

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.

-Lead developer for OutpostHD

http://www.lairworks.com

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.

throw table_exception("(? ???)? ? ???");

When a T is a pointer or reference then const T is not the same as adding const to the thing it refers to. Say T is U *. const T is U * const, a const pointer to non-const U, not const U *, a non-const pointer to const U. So for the purpose of overload resolution foo(U *) and foo(U * const) are the same, but different than foo(const U *).

This topic is closed to new replies.

Advertisement