Does &*x operation create a copy? - c++

I had some problems converting a std::list<MyType>::iterator to MyType*. I have an array of MyType and as I loop through it, I call some void doSomething(const MyType* thing). Eventually I do this:
std::list<MyType> types = ... something here ...;
for( std::list<MyType>::const_iterator it = types.begin(), end = types.end(); it != end; ++it ) {
doSomething(&*it);
}
My question is, whether I do or do not create a memory copy of the MyType by this operation:
&*it
Trying to simply pass the iterator as if it was pointer, or to cast the iterator to pointer raised compiler errors.

No, the sequence of * and & does not create a copy:
* applied to an iterator produces a reference
& applied to a reference produces the address of the original
Neither of these two steps requires copying of MyType's data.
Note: When the presence of an overloaded operator & is a possibility, it is safer to use std::address_of(*it) expression.

One of the requirements for an iterator is that it be derefernceable -- i.e. *it be supported. See http://en.cppreference.com/w/cpp/concept/Iterator. Whether *it returns a reference or a copy is not specified.
In theory, an implementation could return a copy when using *it.
In practice, most implementations return a reference when using *it. Hence, you most likely won't be seeing a copy being made when using &*it.

As long as the iterator is valid it is doing what your want. And no, it does not create a copy.

Based on how your code is written, you are creating a copy of the pointer, but the memory being pointed to by the pointer should not be copied.
Broken down, you take the iterator object (it), you look at the MyType object referenced by the iterator (*it), and then get the address of this object (&*it). The pointer is then copied into the function and used as you desire.

Related

Why cannot it get iterator as reference in c++?

I am learning c++.
I have learned referencing allow us to avoid copying.
So I tried to get an iterator of a vector as reference to overwrite its elements.
// simplified function
std::vector<int>::iterator& GetIterator(std::vector<int>& vec) {
return vec.begin(); // compiler said that here is an error.
}
But compiler give me an error message and suggests to use const reference.
I would not like to use const.
Why cannot it get non-const reference?
Or how to avoid copying of iterator?
Thank you very much.
You can sometimes use a reference to avoid a copy - but here you need a copy. The result of vec.begin() is a temporary which ceases to exist when your function returns. If you want the value outside the function - and you do - then a copy is needed. (If you succeeded in forming a reference here it would be a "dangling reference", which is not a good thing.)
And in any case a lot of types are designed to be copied efficiently, and iterators are amongst those. And in fact the compiler can often avoid the copy for you, without you having to do any work at all - and this is one of those cases.
So the code without the reference is easier, correct, and already optimal.
vec.begin(); return a temporary object and is r-value. You can't bind a l-value reference to a r-value. After returning from GetIterator function, that temporary object will be destroyed and your reference will be dangled.
Return by value (std::vector<int>::iterator) instead of reference. Iterators are designed to be copyable and cheap to copy. Also compilers use Return value optimization to avoid cost of coping objects.
correct code
std::vector<int>::iterator GetIterator(std::vector<int>& vec) {
return vec.begin(); // compiler said that here is an error.
}
your & is extra.
The iterator is like int* and gets a address.
And std::vector< type >::iterator is like that.
So the vector.begin() is like &int so you can not bind it to iterator&

How is x = &(*variable) different from x = variable?

I've been trying to understand c++ by going over some projects and i came across this:
vector<Circle>::iterator circleIt = mCircles.end();
..
mCurrentDragCircle = &(*circleIt);
Why would you dereference and then reference it again?
The *-operator is overloaded for the iterator class. It doesn't do a simple dereference. Instead, it returns a reference to the variable it's currently pointing at. Using the reference operator on this returns a pointer towards the variable.
Using mCurrentDragCircle = circleIt; would assign the iterator to your field.
circleIt is an iterator, and iterators overload operator* so that they look like pointers. Dereferencing an iterator gives a reference to the value; & turns that into a pointer to the value. So this is converting an iterator to a pointer.
Btw., dereferencing past-the-end, i.e. *v.end(), has undefined behavior. The proper way to do this is
v.data() + v.size()
in C++11, or
&v[0] + v.size()
in C++98. Both assume the vector is non-empty.
Because of how iterators works.
*circleIt
will return instance of Circle, e.g. you can do
Circle & c = *circleIt;
Than you take address of that circle and store it into a pointer
Circle * mCurrentDragCircle = & (*circleIt);
Hope this helps.
&* is a particularly pernicious idiom for extracting an underlying pointer. It's frequently used on objects that have an overloaded dereference operator *.
One such class of objects are iterators. The author of your class is attempting to get the address of the underlying datum for some reason. (Two pitfalls here, (i) *end() gives undefined behaviour and (ii) it appears that the author is storing the pointer value; blissfully unaware that modifications on that container could invalidate that value).
You can also see it used with smart pointers to circumvent reference counting.
My advice: avoid if at all possible.

How can you use a reverse iterator with an iterator that is a proxy

Given you have an iterator that is effectively a proxy and contains the data that it returns, how can you make a reverse iterator?
std::reverse_iterator implementation of the dereferencing operator creates a temporary object which it then decrements and dereferences, with code that is something like:
reference operator*() const {
iterator tmp = current;
return *--tmp;
}
with the result that what it returns to you is a pointer to data that goes out of scope before you get hold of it.
This has rather unfortunate results.
How can you get round this?
It looks like you'll need to write your own custom reverse iterator implementation for this specific case since your iterator type is not compatible with this specific implementation of reverse_iterator.
According to http://en.cppreference.com/w/cpp/iterator/reverse_iterator, some implementations do also store a decremented copy of the iterator but not all. Boost::reverse_iterator does not appear to store an additional copy.
I think the standard library implementation is incorrect. If you look at 24.5.1.3.4 [reverse.iter.op.star] in the C++11 standard you'll find the following:
deref_tmp = current;
--deref_tmp;
return *deref_tmp;
Note: This operation must use an auxillary member variable rather than a temporary variable to avoid returning a reference that persists beyond the lifetime of the associated iterator.
In the standard deref_tmp is a for-exposition-only data member of reverse_iterator.

What is the difference between these two parameters in C++?

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

Evaluation of (de)reference operators

I have an (uncommented...) source file which I'm trying to understand.
static const Map *gCurMap;
static std::vector<Map> mapVec;
then
auto e = mapVec.end();
auto i = mapVec.begin();
while(i!=e) {
// ...
const Map *map = gCurMap = &(*(i++));
// ...
}
I don't understand what &(*(i++)) does. It does not compile when just using i++, but to me it looks the same, because I'm "incrementing" i, then I'm requesting the value at the given address and then I'm requesting the address of this value?!
Not at all. &*x is the same as operator&(operator*(x)), which can be anything you want.
It is only true for pointer types like T * p that &*p is the same as p. But C++ has user-defined types and overloadable operators.
The dereference operator (*) is typically overloaded for iterators to return a reference to the container element. The effect of the ampersand operator (&) on the container element is up to the class author; if you want to take the address unconditionally, you should use std::addressof(*i++) (from your fa­vou­rite header<memory>).
mapVec.begin() returns an iterator which has an overloaded operator++. The "dereference" (overloaded operator*) of the iterator is to get to the map object. The reference & is, well, because map is a pointer, so it's being assigned to the address of the object from the dereference of i. We can't do simply i++ because it would still be an iterator, and not the actual map object.
i is an iterator, *i is the object pointed to by that iterator, and &*i is the address of that object. If the iterator were just a plain old pointer, this would be unnecessary, but usually it's not so simple. The iterator is often of some class type that overloads operator* to allow you to access the object it is pointing at. So this is basically a conversion from an iterator to an element to a pointer to that element.
I would move the increment to the next line because it just makes the given line harder to understand. This would be equivalent because the value of i++ is just i and the increment happens afterwards.
It isn't the same: i is an iterator. Dereferencing an iterator yields a reference to some object, i.e., a T& for some type T. Taking the address of such an object yields a T*, i.e., the address of the object at the location i. That the iterator is also incremented in the same expression is just a detail and likely to be a Bad Idea (post increment is typically less efficient than preincrement and there is no real need to post increment the iterator in the code excerpt: it can as well be pre incremented at some other location).