2

I am new to C++ and currently am learning about templates and iterators. I saw some code implementing custom iterators and I'm curious to know what the difference between these two iterator parameters is:

iterator & operator=(iterator i) { ...   i.someVar }
bool operator==(const iterator & i) { ... i.someVar }

They implement the = and == operators for the particular iterator. Assuming the iterator class has a member variable 'someVar', why is one operator implemented using "iterator i" and another with "iterator & i"? Is there any difference between the two "i.someVar" expressions?

I googled a little and found this question Address of array - difference between having an ampersand and no ampersand

to which the answer was "the array is converted to a pointer and its value is the address of the first thing in the array." I'm not sure this is related, but it seems like the only valid explanation I could find.

Thank you!

Community
  • 1
  • 1
mhy
  • 455
  • 2
  • 6
  • 12
  • 1
    possible duplicate of [Pass by Reference / Value in C++](http://stackoverflow.com/questions/410593/pass-by-reference-value-in-c) – Potatoswatter Nov 06 '13 at 00:33
  • Are you asking why an assignment operator would use a by-val parameter, while an equality comparison operator would use a const-reference parameter? There is a very good reason for this, but I'm not going to take the time to answer it if that isn't the question. – WhozCraig Nov 06 '13 at 00:35
  • Disagree with Potatoswatter. The linked question is fairly generic, but `iterator::operator=(iterator)` is the assignment operator. That's a function which warrants specific consideration (Rule of Three, for instance). – MSalters Nov 06 '13 at 09:12

3 Answers3

3

operator= takes its argument by value (a.k.a. by copy). operator == takes its argument by const reference (a.k.a. by address, albeit with a guarantee that the object will not be modified).

An iterator may be/contain a pointer into an array but it is not itself an array.

The ampersand (&) has different contextual meanings. Used in an expression, it behaves as an operator. Used in a declaration such as iterator & i, it forms part of the type iterator & and indicates that i is a reference, as opposed to an object.

For more discussion (with pictures!), see Pass by Reference / Value in C++ and What's the difference between passing by reference vs. passing by value? (this one is language agnostic).

Community
  • 1
  • 1
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • Thank you. It makes a lot of sense that == would take a const reference; comparing equality shouldn't involve changing the things being compared. – mhy Nov 06 '13 at 00:44
  • @mhy Yes, but assigning `a = b` also doesn't change `b`. The other function can also be written using `iterator const &` and was usually done so up until C++11; the difference is a matter of optimization. – Potatoswatter Nov 06 '13 at 00:46
  • @mhy prior to C++11 and move-semantics, it was entirely common (and still is to some degree) to use a param-copy-swap idiom for assignment operators. There are solid reasons behind this, including unifying copy-construction and assignment operator equivalency, as well as exception protection. It is somewhat beyond the scope of your question, but there are indeed logical reasons for using a by-value parameter for the rhs of an assignment operator. (and +1 on the answer) – WhozCraig Nov 06 '13 at 00:58
  • @WhozCraig Param-copy-swap *is* move-semantic. The C++11 idiom does exactly the same thing (only difference is `swap` becomes `move`), but for most of the lifetime of C++98/03, most folks just defaulted to `const &` whether it was the best way or not. – Potatoswatter Nov 06 '13 at 01:24
  • @Potatoswatter really? I never considered it move, since clearly (to me, anyway) it was markedly different. the original rhs was left intact, so to me there was never a move. And I'm somewhat disappointed in the pervasive practice of *not* using it if it (const ref) is as wide-spread as you say it is. it seems such a natural idea, especially with classes that hold dynamic allocation. Heh. I learned something new today, thank you!. – WhozCraig Nov 06 '13 at 01:32
  • @WhozCraig My last comment was wrong; the C++11 idiomatic assignment operator is implemented in terms of `swap` and is fully backward compatible with C++98. Don't worry about common practices; the gap between C++98 and C++11 wasn't stagnation but discovery of how to best use the language. The only change here is that C++11 provides you with a means to initialize the parameter object by destroying the argument. Anyway the implicitly-defined assignment operators don't work this way; the default is to have two overloads by reference. – Potatoswatter Nov 06 '13 at 01:44
  • Actually the `swap` in "copy&swap assignment` often compiled down to a move, as the assignment to a local variable was a dead store. That just optimized out. – MSalters Nov 06 '13 at 09:15
2

the assignment operator = takes the iterator i as value, which means a copy of the original iterator is made and passed to the function so any changes applied to the iterator i inside the operator method won't affect the original.

the comparison operator == takes a constant reference, which denotes that the original object can't/shouldn't be changed in the method. This makes sense since a comparison operator usually only compares objects without changing them. The reference allows to pass a reference to the original iterator which lives outside the method. This means that the actual object won't be copied which is usually faster.

sled
  • 14,525
  • 3
  • 42
  • 70
1

First, you don't have an address of an array here.

There's no semantic difference, unless you try to make a local change to the local variable i: iterator i will allow a local change, while const iterator & i will not.

Many people are used to writing const type & var for function parameters because passing by reference can be faster than by value, especially if type is big and expensive to copy, but in your case, an iterator should be small and cheap to copy, so there's no gain from avoiding copying. (Actually, having a local copy can enhance locality of reference and help optimization, so I would just pass small values by value (by copying).)

musiphil
  • 3,837
  • 2
  • 20
  • 26