In his The C++ Programming Language Stroustrup gives the following example for inc/dec overloading:
class Ptr_to_T {
T* p;
T* array ;
int size;
public:
Ptr_to_T(T* p, T* v, int s); // bind to array v of size s, initial value p
Ptr_to_T(T* p); // bind to single object, initial value p
Ptr_to_T& operator++(); // prefix
Ptr_to_T operator++(int); // postfix
Ptr_to_T& operator--(); // prefix
Ptr_to_T operator--(int); // postfix
T&operator*() ; // prefix
}
Why prefix operators return by reference while postfix operators return by value?
Thanks.
The postfix operator returns a copy of the value before it was incremented, so it pretty much has to return a temporary. The prefix operator does return the current value of the object, so it can return a reference to, well, its current value.
To understand better, you have to imagine (or look at) how are these operators implemented. Typically, the prefix operator++ will be written more or less like this:
MyType& operator++()
{
// do the incrementation
return *this;
}
Since this has been modified "in-place", we can return a reference to the instance in order to avoid a useless copy.
Now, here's the code for the postfix operator++:
MyType operator++(int)
{
MyType tmp(*this); // create a copy of 'this'
++(*this); // use the prefix operator to perform the increment
return tmp; // return the temporary
}
As the postfix operator returns a temporary, it has to return it by value (otherwise, you'll get a dangling reference).
The C++ Faq Lite also has a paragraph on the subject.
Suppose I use overloaded preincrement to increment a private member. Doesn't returning a reference to a private member turns the ++private_var expression to an lvalue thus making it possible to modify the private member directly?
Related
defining function->
car operator *()
{
car temp;
temp.a = a*3;
temp.b = b*3;
return temp;
}
in given below code,how to decide whether * is before o2 or after o2.
car o3=*o2 //o2 is also an object of same class and has some values for a and b
There is only one unary operator that can appear on either side of an object. It is disambiguated by providing two overloads: one that takes only one argument and one that takes an int as its second argument. The compiler knows about that, and calls it appropriately:
struct S {
S& operator++(); // pre-increment
S operator++(int); // post-increment
};
S s;
++s; // calls S::operator++()
s++; // calls S::operator++(int)
Yes, that extra argument is a hack. No, you can't do anything meaningful with its value.
All the other unary operators that can be overloaded appear in the same place as the non-overloaded version. If the operator goes in front of the object in a non-overloaded context (e.g., *ptr), then it goes in front of the object in an overloaded context (e.g., *my_object). If it comes after, it comes after.
I was looking at an iterator class for a linked list and saw this operator overloading and didn't really understand what was going on. I was under the impression that 'int' always has to be declared with a variable name?
void operator++(int)
{
assert(m_node != NULL);
m_node = m_node->m_next;
}
void operator--(int)
{
assert(m_node != NULL);
m_node = m_node->m_prev;
}
Parameter names are always optional. However, the int in this case is special as it denotes this is a postfix operator meaning you are able to do list++ and list--.
Reference: http://en.cppreference.com/w/cpp/language/operators
You can always leave out a parameter name if you want to. If you do that in a normal function definition, that means that an argument must still be provided to the function, but the function doesn't use it:
void f(int) // unnamed parameter
{
// can't use the parameter without a name
}
f(); // ERROR: wants an int
f(42); // OK: takes an int (but ignores it)
In the case of the increment and decrement operators, an unused int parameter is the magic that indicates that this is the postfix operator, x++, not the prefix operator, ++x, which has no parameters.
Because you have two ++ operators, it is a special syntax to differentiate them between post- and pre- incrementation.
void operator++(int)
means postincrementation
void operator++()
means preincrementation
So in your case, you first return, then increase.
void operator++(int)
This means post increment operator. int is just a dummy variable to distinguish it from pre-increment operator. Compiler would pass 0 in its place when calling post increment operator.
I have a constant iterator class which contains the following methods for overloading several operator functions
self_reference operator=( const SDAL_Const_Iter& src ) {
index = src.index;
return *this;
}
self_reference operator++() {
index = index + 1;
return *this;
}
self_type operator++(int) {
SDAL_Const_Iter results = *this;
++index;
return results;
}
The index variable is of type const int.
My compiler is complaining that I am attempting to modify a constant object (More specifically, "Error C2166: l-value specifies constant object"), which I am aware of; however, I see no other way of overloading these functions. Can someone please elaborate on how to go about writing these overloads without causing compiler issues?
I believe the problem is in const int as index variable.
A constant iterator should not allow non-const access to the container's data. The iterator itself, though, is changeable (it has to be able to iterate). Changing index to int should fix the problem.
I was reading a book on data structures, now trying to implement singly-linked list data structure. While implementing iterators, I have come across these implementations of overloaded prefix and postfix increments:
iterator &operator++()
{
this->current = this->current->next;
return *this;
}
iterator &operator++(int)
{
iterator old = *this;
++(*this);
return old;
}
I know that the first one is for prefix and the second one is for postfix, but what I haven't understand is why does overloaded postfix increment have different code? What would be wrong if I do this?
iterator &operator++(int)
{
this->current = this->current->next;
return *this;
}
Thanks in advance.
Actually, both postfix versions are wrong. The postfix iterator must return a copy, not a reference.
The point is that post-increment changes the incremented object, but returns a version of it before the increment. The pre-increment changes the object and returns the incremented version. Their logic must differ accordingly.
This distinction is made because post- and pre-increment have the same semantics on primitive types. Example:
int i = 0;
std::cout << i++ << std::endl;
yields the output 0. Your class with overloaded iterators should imitate that behaviour for consistency. If you had your own integer class with one of the iterator implementations you've shown, the result would be 1, and thereby surprising.
The correct implementation of a postfix increment is in 99% of the cases:
iterator operator++(int)
{
iterator old = *this;
++(*this);
return old;
}
I'm wanting to make sure I understand pass-by-value vs pass-by-reference properly. In particular, I'm looking at the prefix/postfix versions of the increment ++ operator for an object.
Let's suppose we have the following class X:
class X{
private:
int i;
public:
X(){i=0;}
X& operator ++ (){ ++i; return *this; } //prefix increment
X operator ++ (int unused){ //postfix increment
X ret(*this);
i++;
return ret;
}
operator int(){ return i; } //int cast
};
First of all, have I implemented the prefix/postfix increment operators properly?
Second, how memory-efficient is the postfix operator, compared to the prefix operator? Specifically how many X object copies are created when each version of the operator is used?
An explanation of exactly what happens with return-by-reference vs return-by-value might help me understand.
Edit: For example, with the following code...
X a;
X b=a++;
...are a and b now aliases?
It is more idiomatic to call the prefix increment of the object itself in the postfix increment:
X operator++(int)
{
X copy(*this);
++*this; // call the prefix increment
return copy;
}
The logic of incrementing an X object is thus solely contained inside the prefix version.
This is a correct implementation. It is typical that a postfix operator will be worse on performance because you have to create another copy before doing the increment (and this is why I've gotten in the habit of always using prefix unless I need something else).
With return-by-reference, you're returning an l-value reference to the current object. The compiler would typically implement this by returning the address of the current object. This means that returning the object is as simple as returning a number.
However, with return-by-value, a copy must be done. This means there's more information to copy over during the return (instead of just an address) as well as a copy constructor to call. This is where your performance hit comes in.
The efficiency of your implementation looks on-par with typical implementations.
EDIT:
With regards to your addendum, no, they are not aliases. You have created two separate objects. When you return by value (and when you created a new object from within the postfix increment operator) this new object is placed in a distinct memory location.
However, in the following code, a and b are aliases:
int a = 0;
int& b = ++a;
b is an address which references a.
Your operators are implemented correctly.
In the prefix operator, no copies of X are made.
In the postfix operator, one copy is made for ret, and potentially another copy is made when returning from the function, but all compilers will elide this copy.