Is the reference-token(&) useless clutter?

  • (2 Pages)
  • +
  • 1
  • 2

23 Replies - 9346 Views - Last Post: 26 August 2013 - 06:58 AM

#1 squarepenguin  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 34
  • Joined: 16-May 12

Is the reference-token(&) useless clutter?

Posted 18 August 2013 - 02:34 PM

Greetings, fellow programmers!

After reading this blog post, I learned that decent compilers have Return Value Optimization.

Nuances aside: It changes return-by-value to return-by-reference where it is faster.

Does that mean that manualy adding &'s to your arguments is as usefull as adding the register-keyword to your variables?

Is This A Good Question/Topic? 0
  • +

Replies To: Is the reference-token(&) useless clutter?

#2 jimblumberg  Icon User is offline

  • member icon


Reputation: 4293
  • View blog
  • Posts: 13,459
  • Joined: 25-December 09

Re: Is the reference-token(&) useless clutter?

Posted 18 August 2013 - 03:08 PM

Quote

Does that mean that manualy adding &'s to your arguments is as usefull as adding the register-keyword to your variables?

No.

Show an example to illustrate your question.


Jim
Was This Post Helpful? 0
  • +
  • -

#3 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1623
  • View blog
  • Posts: 5,714
  • Joined: 03-August 09

Re: Is the reference-token(&) useless clutter?

Posted 18 August 2013 - 03:13 PM

Why do you think there is any correlation in performance between registers and pass/return by reference? Both can improve performance under certain cases but they are by no means equivalent and you shouldn't full yourself into thinking so. Also DON'T use the register keyword unless you REALLY have to optimize something. It severally limits how you can do things (take references, pass by reference, etc...) and generally the compiler does a pretty damn good job of register allocation so it wont yield you very good performance gains. The register keyword only helps with micro optimization. Passing by reference helps with macro optimization like avoiding coping a large array. They are two very different things.

That said here are some basic rules for C++98/03 for how arguments should be passed:
  • if the type of an argument is a built in type to be used only as input, pass by value
  • if the type of an argument is a user defined type to be used only as input, pass by const reference
  • if the type of an argument is to be used a means of returning a value, pass by reference
  • if the type is unknown because of a template (that is it could be user defined or primitive) and to be used only as input pass by const reference


Try to avoid returning arguments by reference (explicitly that is, RVO may do this for you). It leads to an extremely procedural style and wont work [well] with objects that can't be default constructed. With objects that can't be default constructed you can't initialize these objects with the value from the function. With objects that can be default constructed you waste a call to the default constructor by then using the return by reference value of a function (C# has the 'out' keyword for this). Prefer returning items by value or reformulating your design. Generally this means preferring immutable methods rather than stateful methods.

In C++11 because of move semantics I even more strongly take the point above because returning items by rvalue can avoid almost all unnecessary constructor calls. This also allows you to work with arbitrarily large objects without relaying on return by reference. There is also an additional rule for C++11

rules for C++11
  • if the type of an argument is a built in type to be used only as input, pass by value
  • if the type of an argument is a user defined type to be used only as input, pass by const reference
  • if the type of an argument is to be used a means of returning a value, pass by reference
  • if the type of an argument is deduced at compile time, declare the argument as an rvalue reference (this gives you best of both worlds). see Scott Myers universal reference
  • if there is a potential significant gain from recycling an object but the type is not deduced create both a const ref version and an rvalue reference version. if the copy needs to be made in the const ref version any how it can just call the rvalue reference type with a copy so that you only have 1 definition. Unfortunately sometimes you can't actually get away with this and end up with two definitions but it is rare if you play you cards right.


If you are really getting into optimization there are sometimes reasons to pass by value with larger objects but I claim that the interface of such functions are subject to change. Changing your public interface is the LAST thing you want so the above rules should be used in your public interface. In such a case you could have a public interface function that uses a const reference and then creates a copy for the non-public interface version.

This post has been edited by ishkabible: 18 August 2013 - 06:33 PM

Was This Post Helpful? 2
  • +
  • -

#4 squarepenguin  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 34
  • Joined: 16-May 12

Re: Is the reference-token(&) useless clutter?

Posted 18 August 2013 - 03:32 PM

Thanks for the replies.

about the registry-keyword: I was under the impression that it did nothing on modern compilers. I was therefore asking if passing arguments by reference does anything with optimizations.
Was This Post Helpful? 0
  • +
  • -

#5 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2153
  • View blog
  • Posts: 3,315
  • Joined: 21-June 11

Re: Is the reference-token(&) useless clutter?

Posted 18 August 2013 - 03:50 PM

View Postsquarepenguin, on 18 August 2013 - 11:34 PM, said:

Nuances aside: It changes return-by-value to return-by-reference where it is faster.


That's really not true. It avoids copying where possible, but it does not allow you to do things that you can with references. If you want the caller to be able to change the variable (or array element or whatever) that you're returning a reference to, then it is not possible to remove the &. Returning by value will not allow the caller to modify the variable that you're returning - RVO or not.

Quote

Does that mean that manualy adding &'s to your arguments is as usefull as adding the register-keyword to your variables?


To your arguments or to your return type? Either way the answer is no. If you want to be able to modify the variable that the caller passed in, you need to take a reference as your argument. If you want the user to modify the variable you're returning, you need to return a reference.

As a real-world example vector's (as well as list's, map's, set's etc.) operator[] and at() methods return a T&. This allows you to write something like myvec[i] = x; or myvec.at(i) = x; and have it work as expected. If those methods returned by value instead, this would not work and most data structures would basically become unusable.

View Postishkabible, on 19 August 2013 - 12:13 AM, said:

Try to avoid returning arguments by reference (explicitly that is, RVO may do this for you). It leads to an extremely procedural style and wont work with objects that can't be default constructed.


Why can't objects that can't be default constructed not be returned by reference?
Was This Post Helpful? 0
  • +
  • -

#6 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1623
  • View blog
  • Posts: 5,714
  • Joined: 03-August 09

Re: Is the reference-token(&) useless clutter?

Posted 18 August 2013 - 04:38 PM

Quote

about the registry-keyword: I was under the impression that it did nothing on modern compilers. I was therefore asking if passing arguments by reference does anything with optimizations.


This question assumes that there isn't a semantic difference between pass by value and pass by reference. There is a huge semantic difference that makes that can make the performance difference between O(n) and (n^2) in some cases; that is, the algorithm you are using changes not just the code. Your thinking of it as some kind of petty micro optimization when it is actually a semantic tool that just happens to in some cases improve micro performance (by value objects of size >=64 bytes for instance) but by not particular design and rather by consequence of other intentions. It literally changes the observable effects of the language in a defined way; this is not the case for the register keyword.

point: Passing by reference changes the semantics of the code. It can drastically change the defined behavior of the program. the register keyword limits you trade off limiting functionality of a variable (i.e. a subset of functionality) for a potential performance gain. This gain is in most cases pretty meager.

Quote

Why can't objects that can't be default constructed not be returned by reference?

I meant to say that they can't be initialized in this manner and also that attempt to initialize a variable in this manner you are wasting a constructor call. I said the wrong thing. Thank you for catching that. I'll edit it now.

This post has been edited by ishkabible: 18 August 2013 - 04:49 PM

Was This Post Helpful? 0
  • +
  • -

#7 raspinudo  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 61
  • View blog
  • Posts: 232
  • Joined: 19-September 11

Re: Is the reference-token(&) useless clutter?

Posted 19 August 2013 - 09:26 AM

While most compilers support RVO, it is still bad practice(IMO), to write code based on a compiler feature. Imagine your code needs to be ported to some embedded environment with a really bunk compiler, all those assumptions are useless.
Was This Post Helpful? 0
  • +
  • -

#8 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 687
  • View blog
  • Posts: 2,377
  • Joined: 31-December 10

Re: Is the reference-token(&) useless clutter?

Posted 19 August 2013 - 09:56 AM

View Postraspinudo, on 19 August 2013 - 12:26 PM, said:

While most compilers support RVO, it is still bad practice(IMO), to write code based on a compiler feature. Imagine your code needs to be ported to some embedded environment with a really bunk compiler, all those assumptions are useless.

This is a good point and it goes along with what someone else already said, and that is that compilers are better at optimizing code than humans are, so for the most part you should just let the compiler do its thing. One of the only C++ features that should use is the inline keyword and possibly volatile/mutable.
Was This Post Helpful? 1
  • +
  • -

#9 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1623
  • View blog
  • Posts: 5,714
  • Joined: 03-August 09

Re: Is the reference-token(&) useless clutter?

Posted 19 August 2013 - 11:12 AM

Quote

One of the only C++ features that should use is the inline keyword and possibly volatile/mutable


I'm going to interpret this to mean "one of the only optimization/lesser used features that you should ever use are...". Inline can have an effect but compilers are getting better and better at deciding how to inline. Really all the inline keyword tells compilers is that that bit of code is run a lot which effectively takes the place of the complex (and sometimes impossible) analysis required to figure out the relative number of times a chunk of code is run. The register keyword is the analog for variable use but as it turns out compilers are pretty good at figuring out where the inner loop is and choosing registers for the most used variables so this input from the human is no longer needed. volatile/mutable change semantics so I'm not sure they are in the same basket. volatile can probably be used to alter performance but that sounds pretty sketchy to me personally; volatile should be best kept to systems programming I think. I don't think mutable will change performance at all but I could be wrong; I've only come across a few cases involving thread safety, lazy evaluation, and some code that I wanted to be extremely generic involving functions (I wanted even non-const functions to be able to be called in an otherwise const bit of code). So I do use mutable on a very rare occasion. If you are optimizing then the inline keyword is a good safe place to start so it's fairly common to see it.

Quote

While most compilers support RVO, it is still bad practice(IMO), to write code based on a compiler feature.

This is kind of misleading IMO. You should write code in a clean way first and forget about optimization. When optimization comes calling you should change your code in the least invasive way that fixes the issue and then be done with it. This keeps your code base manageable. Saying you shouldn't relay on a feature that allows you to get away with clean code first and not worry about optimization seems like bad advice. If and only if you have to compile code on a bad compiler on a bad system should you attempt to fix it.

My advice: relay on it first if it makes you feel better about your code and then if and only if there are performance issues fix your code in the way that makes sense (which likely has nothing to do with RVO). Note that finding a different compiler might be a better option. IF it does have something to do with RVO then fix it only where it is critical and be done with it.

This post has been edited by ishkabible: 19 August 2013 - 11:19 AM

Was This Post Helpful? 1
  • +
  • -

#10 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5941
  • View blog
  • Posts: 12,870
  • Joined: 16-October 07

Re: Is the reference-token(&) useless clutter?

Posted 19 August 2013 - 12:50 PM

The "C" object in the example isn't an instance of anything all. It had no data. How does this rather odd assertion work if C is something like struct C { int foo; char bar[10000]; }...
Was This Post Helpful? 0
  • +
  • -

#11 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2153
  • View blog
  • Posts: 3,315
  • Joined: 21-June 11

Re: Is the reference-token(&) useless clutter?

Posted 19 August 2013 - 01:13 PM

View Postishkabible, on 19 August 2013 - 08:12 PM, said:

Really all the inline keyword tells compilers is that that bit of code is run a lot


It also allows you to put function definitions in header files, which allows compilers to inline functions when they would otherwise not be able to. Though I suppose compiler support for link-time optimizations makes that unnecessary if enabled.
Was This Post Helpful? 0
  • +
  • -

#12 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1623
  • View blog
  • Posts: 5,714
  • Joined: 03-August 09

Re: Is the reference-token(&) useless clutter?

Posted 19 August 2013 - 05:05 PM

Most of the code I write ends up in headers for some reason. Most is inside function definitions so I don't need to explicitly say "inline". The other main bit of code is generally template functions. What's left I generally declare as static and not inline. You are right however, there IS a semantic difference that I was looking over; good catch!

LTO is another optimization that lets the programmer take their mind off of petty optimization details. I really hope to see more of it in the future.
Was This Post Helpful? 0
  • +
  • -

#13 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 687
  • View blog
  • Posts: 2,377
  • Joined: 31-December 10

Re: Is the reference-token(&) useless clutter?

Posted 20 August 2013 - 11:15 AM

To say that volatile and mutable are in a different basket is a little off base. volatile tells the compiler NOT to put the variable in a register so from my understanding that's like telling the compiler not to optimize in that case. Then mutable is for variables that change a lot, and can even be changed inside const member functions. So it's letting the compiler know how that variable can be handled. In my opinion, both of those help the compiler decide if it should optimize or not. So wouldn't that put them in the same basket?
Was This Post Helpful? 0
  • +
  • -

#14 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1623
  • View blog
  • Posts: 5,714
  • Joined: 03-August 09

Re: Is the reference-token(&) useless clutter?

Posted 20 August 2013 - 11:55 AM

You and I have very different ideas of what mutable and volatile are. Inline's primary purpose is to hint to the compiler an optimization should be preformed. This is not the case with volatile and mutable. volatile changes run time semantics which MAY in turn effect performance but I could equally say that about prefix ++ or postfix ++. Mutable changes compile time semantics to subvert the type checker to a degree. The only thing about that related to the run time is that it lets code compile that would otherwise not compile.

Volatile says to keep a variable in memory. This may have the effect of saying "don't optimize" but they aren't the same thing. It has a number of usages in systems programming from what I understand. It guarantees that any changes to a variable, even small intermediate ones, can be observed by another bit of code (say in another thread. note that I'm not saying this is synchronizing the object at all).

Mutable does NOT tell the compiler that a variable changes a lot. It JUST lets you change the value in a const context; that's it. If compilers are using that as a hint then that is behavior they have come up with on their own. Do you have documentation or a source that says that mutable is used as a hint to the compiler?

This post has been edited by ishkabible: 20 August 2013 - 12:04 PM

Was This Post Helpful? 0
  • +
  • -

#15 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 687
  • View blog
  • Posts: 2,377
  • Joined: 31-December 10

Re: Is the reference-token(&) useless clutter?

Posted 20 August 2013 - 12:10 PM

http://en.wikipedia....latile_variable
and this one too:
http://en.cppreferen...cpp/language/cv

*EDIT*:
Just a few quotes from those links:

Quote

Generally speaking, the volatile keyword is intended to prevent the compiler from applying certain optimizations which it might have otherwise applied because ordinarily it is assumed variables cannot change value "on their own."

Quote

Operations on volatile variables are not atomic, nor do they establish a proper happens-before relationship for threading. This is according to the relevant standards (C, C++, POSIX, WIN32),[2] and this is the matter of fact for the vast majority of current implementations. Thus, the usage of volatile keyword as a portable synchronization mechanism is discouraged by many C/C++ groups.


This quote is from the C++ ARM page 110:

Quote

There are no implementation-independent semantics for volatile objects. volatile is a hint to the compiler to avoid aggressive optimization involving the object because the value of the object may be changed by means undetectable by a compiler.


*EDIT2*:
Ishkabible, please don't change your post the way you are. If you mispeak, just strikethrough the wrong text, and add the new stuff to the end.

This post has been edited by vividexstance: 20 August 2013 - 12:27 PM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2