C++ return reference variable in prefix overloading - c++

I am confused when all the code I find shows returning a reference variable when overloading the prefix operator. I went through the parashift.com FAQ (http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.14) and it isn't clear, even though it says it WILL be clear when you read it. I adapted their example into a nonsensical, pointless little program to test.
#include<iostream>
using namespace std;
class Number {
public:
Number& operator++ (); // prefix ++
Number operator++ (int); // postfix ++
int value() { return value_; }
void setValue(int value) { value_ = value; }
private:
int value_;
};
Number& Number::operator++ () {
++value_;
return *this;
}
Number Number::operator++ (int unused) {
Number temp;
temp.setValue(value_);
++value_;
return temp;
}
int main()
{
Number someNum;
someNum.setValue(20);
cout << "someNum : " << someNum.value() << "\n";
someNum++;
++someNum;
cout << "someNum : " << someNum.value() << "\n";
return 0;
}
The problem is, it works if I just declare it as a Number object as well like so:
#include<iostream>
using namespace std;
class Number {
public:
Number operator++ (); // prefix ++
Number operator++ (int); // postfix ++
int value() { return value_; }
void setValue(int value) { value_ = value; }
private:
int value_;
};
Number Number::operator++ () {
++value_;
return *this;
}
Number Number::operator++ (int unused) {
Number temp;
temp.setValue(value_);
++value_;
return temp;
}
int main()
{
Number someNum;
someNum.setValue(20);
cout << "someNum : " << someNum.value() << "\n";
someNum++;
++someNum;
cout << "someNum : " << someNum.value() << "\n";
return 0;
}
I assume I simply need a better understanding of reference variables. Can anyone explain simply why the prefix operator SHOULD be coded as returning a reference variable?

The difference between :
Number& Number::operator++ () {
++value_;
return *this;
}
and
Number Number::operator++ () {
++value_;
return *this;
}
is that, when you use the first code, the following expression:
++(++(++someNum));
increments someNum THRICE. See the output here: http://ideone.com/y9UlY
However, when you use the second one, this
++(++(++someNum));
increments someNum just ONCE!! See the output here: http://ideone.com/eOLdj
It is because when you return the reference from operator++(), the second and third ++ invokes on the same object called someNum and therefore, it increments the same object, all the times. But when you return by value, the second and third ++ invokes on the temporary object which you returned from operator++(). Hence, the second and third call doesn't increment someNum, instead it increments the temporary objects which get destroyed at the end of the expression.
Now if the temporary objects get destroyed, why create then in the first place? After all, its pre-increment operator, which means the temporary and the original object will have the same value. So the good design decision is, return by reference when defining pre-increment operator, to avoid creating temporary, and improve performance.

First, there's an efficiency issue. You are creating a new instance of the class in order to return it for no reason.
Second, there's the semantic issue. Your code invokes the empty constructor or the copy constructor to make the temporary and then destructs the temporary. If that has semantic meaning that's inappropriate, then the code doesn't really work, it just appears to.
Third, the code returns the wrong thing. Consider: ++foo.do_something();. With your code, we call 'do_something' on the temporary object. We wanted to call do_something() on the pre-incremented foo.

Related

I was doing code on operator overloading . while i encoutered a strange behaviour can any one explain it? [duplicate]

This question already has answers here:
Why use int as an argument for post-increment operator overload?
(2 answers)
Overloading ++ for both pre and post increment
(4 answers)
Closed 8 months ago.
** Pre Increment **
#include <iostream>
using namespace std;
class demo {
int i;
public:
demo (int b = 0) {
i = b;
}
void display() {
cout<<"Number is " <<i<<endl;
}
void operator ++() {
i = ++i;
}
};
int main() {
demo obj(5);
obj.display();
++obj;
obj.display();
return 0;
}
In this case operator function took no function argument
** Post Increment **
#include <iostream>
using namespace std;
class demo{
int i;
public:
demo (int b = 0 ){
i = b;
}
void display(){
cout<<"Number is " <<i<<endl;
}
void operator++(int){
i = i++;
}
};
int main(){
demo obj(5);
obj.display();
obj++;
obj.display();
return 0;
}
While in this code the function took the int as and argument
In these codes almost everything is same except for the fact that in one code void operator ++() takes a argument int while in other it doesn't .
What could be the possible reason of such behaviour ?
If you are asking why one takes a parameter and one does not. I could only say, that is just the syntactical convention in C++ to distinguish prefix increment and postfix increment.
In your above code, the resultant object is always incremented after you use the operator ++. Therefore, you would not likely to see a desirable result. You can only notice their difference it you assign demo x = a++; or demo x = ++a; (getting their current value), and then print the value out.
To do that, you have to do something like below:
Prefix increment increases, and return itself.
demo& operator ++() {
i = i + 1;
return *this; // Return itself after incremented
}
Meanwhile, postfix increment creates a duplicate object, increases itself, and return the duplicate one.
demo operator++() {
demo duplicate(i);
i = i + 1;
return duplicate; // Return the itself but before incremented.
}
You can read this familiar post: Overloading ++ for both pre and post increment

how to overload << operator in c++ to use repeatedly?

Sorry for the not clear title.
Recently I started to learn C++ and I don't know how to overload operator << to make it repeatable.
Here's an example code.
class Foo{
private:
int* a;
int idx = 0;
public:
Foo(){a = new int[100];
void operator<< (int a) {arr[idx++] = a;}
What << does is basically class get integer number as an operand and save it into arr.(Ignore overflow case here)
For example, a << 100 will add 100 into array.
What I want to do is make << operator can be repeatedly used inline like a << 100 << 200
How should I fix above code to allow this function?
Thanks in advance :)
The overloaded Foo::operator<<() takes actually two arguments:
The parameter int given as right-hand side
The implicit this from left-hand side.
To allow chaining of this operator, it should return a reference to the left-hand-side (i.e. *this) to become usable at left-hand-side itself.
Sample code:
#include <iostream>
struct Foo {
Foo& operator<<(int a)
{
std::cout << ' ' << a;
return *this;
}
};
int main()
{
Foo foo;
foo << 1 << 2 << 3;
}
Output:
1 2 3
Live demo on coliru
Chaining is enabled by returning a reference to the instance so you can call another method:
class Foo{
private:
std::vector<int> a;
public:
Foo(){}
Foo& operator<< (int a) {
arr.push_back(a);
return *this;
}
};
Now you can call f << 100 << 200 << 42;.
Note that I replaced the array with a std::vector to make Foo less broken (unless you have a descrutor that you did not show it was leaking memory, you could fix that, but then still copying would cause problems, in short you need to respect the rule of 3/5 when you own a resource, using a std::vector makes things much simpler).
PS: Same works for other methods. You simply call another method on the returned reference to this. Note that operators are just methods (with some syntactic sugar) and to see that you can write as well f.operator<<(100).operator<<(200).operator<<(42);.
Return a reference to *this. It's unrelated but you should use a vector to avoid memory leaks. Try to avoid raw new
class Foo{
private:
std::vector<int> a;
public:
Foo &operator<< (int a) {
arr.push_back(a);
return *this;
}
};

how to overload assignment operator on class member variable

I am trying to track the value of a variable that I will input in an API function.
One option is to overload the assignment operator and put some code there. But how would I overload an assigment operator on a member variable of a class?
#include <iostream>
using namespace std;
template <class T>
class MonitoredVariable1
{
public:
MonitoredVariable1() { }
MonitoredVariable1(const T& value) : m_value(value) {}
operator T() const { return m_value; }
T val;
T& operator = (const T& value)
{
val = value;
m_value = value;
std::cout << "value updated" << " \n"; //THIS NEVER GET PRINTED!!!
return val;
}
private:
T m_value;
};
int main()
{
MonitoredVariable1<double> MonitoredVariable;
MonitoredVariable.val = 10.2;
std::cout << "main done..." << " \n";
return 0;
}
To monitor changes to the variable, you need to be assigning to the class, not the contained variable.
First, get rid of val. Only have the private m_value value. This way all accesses have to go thru your member functions that can track the changes.
operator= should return a reference to the class (return *this;), not the value.
Assignment is to the class object:
MonitoredVariable = 10.2;
You can only overload assignment on a class. But you can make that variable to be of a class type with overloaded assignment, like:
class Monitor {
class Monitored {
double x;
public:
Monitored &operator= (double v) {
std::cout << "Assigned " << v << std::endl;
x = v;
return *this; // don’t forget this!
}
operator double() const {
std::cout << "Accessed " << x << std::endl;
return x;
}
};
Monitored val;
};
You may need to overload more operators, and also to pass a reference to Monitor into val (there are tricks to calculate it instead if you’re short on memory).
You can (in modern C++) even overload the & operator, but unless the API function is a template, it has to return pointer. Watching for access through it is very environment-specific.
During debugging, you can usually set a memory watchpoint that will pause program execution on writing to, or even on reading from, a particular memory location (for GDB, see Setting Watchpoints; VS should have a similar feature). That requires hardware support (or debugger-interpreter which is insanely slow), though, so the overall number of watchpoints is often very limited.
Without a debugger, you may be able to make a one-shot watch using memory protection tricks (like protecting the page containing the variable, and unprotecting it on first SEGV) but that’s all too fragile for normal use.

How post-increment operator works with user defined types?

I have a difficulty on how this post-increment operator works for user-defined types: As I guess the Post-Increment operator operator++(T _unused) saves the original value first (into the expression) then increment the variable. e.g:
int x{5};
int y{x++};
So x = 6 and y = 5 and that's ok.
But here is an example of user-defined:
struct s{
int x;
s(int m_) : x(m_){}
s operator++(int){ x++; return *this;}
};
int main(){
s a(0);
a.x = 7;
cout << "a::x: " << a.x << endl;
s b(a++);
cout << "a::x: " << a.x << endl; // 8
cout << "b::x: " << b.x << endl; // 8 ?!
int t = 9;
s c(t++);
cout << "c::x: " << c.x << endl; // 9
cout << "t: " << t << endl; // 10 ok
cout << endl;
return 0;
}
As you can see above: s b(a++) will make the values of a.x and b.x 8? I can't understand why?
Thank you guys for your help and time and efforts.
How post-increment operator works with user defined types?
The way you write it, as it is mostly a regular method.
It is good practice to avoid surprise, and so mimic behaviour of built-in types is good.
To mimic built-in type as int, you might fix implementation to:
struct s
{
int x;
explicit s(int m_) : x(m_){}
s& operator++(){ ++x; return *this;} // pre-increment
s operator++(int){ auto res = *this; ++*this; return res;} // post-increment
};
Change the operator to this:
s operator++(int){
s t{x++};
return t;
}
The problem is that you're defining the operator in a way that it modify this before returning and the return is a copy of this modified, what you need is create a new s with the value of x before modification and return that instead.
You don't get a post-increment just by adding int to the function signature: you have to actually implement it!
Your code:
s operator++(int){ x++; return *this;}
This looks just like a pre-increment to me. Although it'll be called when you write someSObject++, all it does is increment the object's own x then return a copy of the object.
Instead, I think you meant something like:
s operator++(int)
{
S result{*this};
++(*this);
return result;
}
Or, tailored to this specific class for brevity:
s operator++(int)
{
return s{x++};
}
You typically provide two overloads for the increment operator in a class:
class C {
public:
C& operator++(); // pre-increment
C operator++(int); // post-increment
int i;
};
The thing is, naming these "pre-increment" and "post-increment" describes how they're called, not what they do.
C c;
++c; // calls operator++()
c++; // calls operator++(int)
To implement the usual semantics of pre- and post-increment you have to write code that does the appropriate thing.
Pre-increment means incrementing the value, and returning the new value:
C& C::operator++() {
++i;
return *this;
}
Post-increment means incrementing the value and returning the old value:
C C::operator++(int) {
C res(*this);
++*this;
return res;
}
What should you expect from: s operator++(int){ x++; return *this;}?
You can see that x is incremented before the copy constructor constructs the temporary object. Remember returning by value invokes copy constructor. You should construct the temporary object before incrementing the variable.
In your case you can change it to look like:
s operator++(int){
return s(x++);
}
AS you can see above the temporary object is constructed with x's value then x is incremented.

Some troubles with C++ template pointer-to-member based property realization

My target was to make properties in C++ like in C# - with non-trivial set/get behavior.
Here, object of Property holds refs to master of the prop and its set/get methods.
Realisation, content of Property.h:
#include <iostream>
using namespace std;
namespace First {
template <class Master, class Type>
struct Property
{
Master &master;
const Type (Master::*&get) () const;
Type (Master::*&set)(Type value);
Property
(
Master &master,
const Type (Master::*get) () const,
Type (Master::*set)(Type value)
):
get(get),
set(set),
master(master)
{ }
operator const Type() const { cout << "inside" << endl; return (master.*get)(); }
Type operator = (Type value)
{
return (master.*set)(value);
}
};
// Test chamber.
class R
{
float x;
const float getx() const { cout << "returning " << 0 << endl; return 0; }
float setx(float value) { cout << "setting " << value << " in place of " << x << endl; return x = value; }
public:
Property<R, float> X;
R(): X(*this, &R::getx, &R::setx) { }
};
}
I also created .cpp file:
#include "Property.h"
using namespace First;
int main()
{
R r;
r.X = 10;
float y = r.X;
}
The program makes "assign" step, printing 'setting 0 to 10', but segfaults on call to "retrieve" step, no difference what code (or no at all) inside 'R::getx()'.
~/Sources$ ./a.out
setting 10 in place of 0
inside
zsh: segmentation fault ./a.out
It seems that call to (master.*get()) itself causes a failure. What is wrong in this code?
UPD: A tested out that any other call to master's functions leads to segfault, only one call of (master.*set) successes. Seems that this call invalidates state of object, member-to-ptr, Property itself or Moon phase.
const Type (Master::*&get) () const;
Type (Master::*&set)(Type value);
Remove & from the above definitions. Because of &, each of these bound to the constructor parameters which do not exist after the constructor returns.
Also note that it seems that (master.*set)(value) works, its because you're unlucky. Its actually invokes undefined behavior. But you're lucky that very soon you come to know the problem when (master.*get)() fails, giving segfault.
Use:
const Type (Master::*get) () const;
Type (Master::*set)(Type value);
It should work now, without any problem, as it would cause copy of the addresses in the initialization-list, rather than referring to the parameters!
segfault : http://ideone.com/46RrU (your original code)
no fault : http://ideone.com/PljI4 (after fixing)