Jump to content
  • Advertisement
Sign in to follow this  
DrEvil

c++ const correctness

This topic is 4719 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

I learned to code using const whenever possible on setter methods, on getter methods, on member functions, etc.. especially when returning non trivial data types such as matrices, vectors, quaternions by reference or pointer. ex: bad = void SetPosition(Vector3 &pos); good = void SetPosition(const Vector3 &pos); bad = void SetOrientation(Quaternion &rot); good = void SetOrientation(const Quaternion &rot); I don't exactly remember all of the reasons why these habits are a good idea, other than the obvious one of preventing modification of the original values. Are there other reasons why these are a good idea? I'd like to know as many of the benefits as possible to make a better case against some who don't see the benefit. Additionally, I've always learned to write accessor functions to return const & as well, as opposed to passing parameters that will then be filled in. ex: I like const Vector3 &GetPosition(); const Quaternion &GetOrientation(); as opposed to the common directx method of void GetPosition(Vector3 &pos); void GetOrientation(Quaternion &pos); DirectX tries to fake the benefits of the first by sometimes returning the pointer so it can be used as function parameters, but IMO I much prefer the first method. In theory it would seem better in terms of code readability, code length, and even speed, due to fewer temporary objects being created. This second point is arguably more about preference than proper code style, while the first I believe is rooted more in proper design. Any opinions either way? Or additions to the benefits of any of these methods? Thanks J

Share this post


Link to post
Share on other sites
Advertisement
One of the absolutly top reasons for being const correct is that it's a form of documentation a form of contract that help other programmers utilize your code correctly. From that standpoint it also helps them write correct and fast code since they don't have to doubt wheter their objects will change when calling some specific function. (I disregard the mischviousness that is named const_cast)

Share this post


Link to post
Share on other sites
I don't like specifying output argument through a non-const reference, just because it isn't obvious to the caller that his value is getting changed. If it's an output parameter I'll use a pointer, and for an input a const reference. Using a non-const reference for an input-only parameter is really bad stuff.

I also like your way of Get() functions as opposed to DirectX, simply because you can initialize to const variables.

Your way:

const Quaternion q = obj.GetOrientation();

Doesn't work:

const Quaternion q;
obj.GetOrientation(&q); // Nope!


Some people will also overload the non-const return type with a non-const accessor:

const Quaternion& Orientation() const { return m_orientation; }
Quaternion& Orientation() { return m_orientation; }

and the compiler will choose which one to use based on whether in used in a const/non-const context. This one's a little slipperier because suddenly non-const references to internal data are floating around, but even so generally pretty useful.

Share this post


Link to post
Share on other sites
Quote:
Original post by DrEvil
Additionally, I've always learned to write accessor functions to return const & as well, as opposed to passing parameters that will then be filled in.

ex:
I like
const Vector3 &GetPosition();
const Quaternion &GetOrientation();

as opposed to the common directx method of
void GetPosition(Vector3 &pos);
void GetOrientation(Quaternion &pos);

DirectX tries to fake the benefits of the first by sometimes returning the pointer so it can be used as function parameters, but IMO I much prefer the first method. In theory it would seem better in terms of code readability, code length, and even speed, due to fewer temporary objects being created.

The latter might be a result of (trying to) keep consistent interface with functions which may attempt to modify provided object, and return indication of how this try went..?

// pseudocode
bool foo( bar& Bar );

main() {

bar Bar;
std::cout << ( foo(Bar) ? "Bar was foo'ed" : "Bar wasn't foo'ed" ) << "\n";
}

just a bit different thing. ^^;

Share this post


Link to post
Share on other sites
Yes, I can see use in passing the variable to be filled in in some situations, and using the return value as an error code. I don't mean to imply this should never be done, the question is more meant for instances where there is no error condition to check, typical of many simple accessors/modifiers.

Share this post


Link to post
Share on other sites
Quote:
Original post by DrEvil
DirectX tries to fake the benefits of the first by sometimes returning the pointer so it can be used as function parameters, but IMO I much prefer the first method. In theory it would seem better in terms of code readability, code length, and even speed, due to fewer temporary objects being created.


DirectX is backwards compatible with C. References are not supported in C.

Also, many of the functions that are guilty of this in the DX libraries are standalone C style functions. Even if we were to ignore C backwards compatibility, they still wouldn't be able to use your method because it would require them to return a reference to a local variable. Which is a big no-no.

Share this post


Link to post
Share on other sites
Among other things, const correctness lets you pass in constants.

Consider:

void fn(const std::string& x)
{
}

void fn2(std::string& x)
{
}

int main()
{
fn("oh ho! this works");
fn2("oh teh noes! this doesn't work");
}


Share this post


Link to post
Share on other sites
Good points sandman, I knew C compatibility was one of the reasons, but hadn't thought about the fact that most of the functions perform some level of computation where they need a place to return the result, and returning by value would definately be a bad idea. DX wasn't a very good example to mention.

The reason I posted is because I'm working on a project that is almost entirely built on that method, even for trivial functions like the ones shown above. I'd like to present the alternative and the benefits, I just want to know the pros and cons beforehand to present a more educated analysis other than "this is just how I prefer it".

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!