return *this to a Date& operator++()

I would love to be able to get a deeper understanding of this code from the book & I will arrange in FACTS that I think I know vs QUESTIONS to facilitate.

FACT1:
this->day; //Like saying address of object &holiday.........holiday.day; (if day was public)

&holiday = 0x7bfde0 //All 3 lines verify to same &holiday address...great!
(unsigned int*)this = 0x7bfde0
this = 0x7bfde0

FACT2:
I thought that when you instantiate an object that it makes it's own copies of the attributes AND functions, but then today I read that there is only 1x instance of functions and that all objects use that instance of the functions but have their copy of the attributes.

QUESTION1:
1A) Date& operator ++ () {.......return *this;}

If the object itself used the operator in the main, "++holiday;" then shouldn't the compiler be smart enough to let me use "return this;" which would send the address of the object & connect to the return "Date&"....they would both then be address value of object? I am still having a disconnect somehwere here to be able to fully understand WHY this is this way?

return this; //Gives error below

"[Error] invalid initialization of non-const reference of type 'Date&' from an rvalue of type 'Date*'"

We can send pointers to functions and have parameter on the function end accept the pass by reference "&", so why wouldn't this work? Can't assign an address from a right value pointer...why not if "this" has the address of the object as verified by the code?
Or is this just another one of those C++ rules, can NEVER assign a pointer to an address (no R-value)?
Book says can't assign pointers to arrays, but can arrays to pointers & I think that was about it.

cout << "this = " << this << endl; //0x7bfde0 & I did not have to use *this
&holiday = 0x7bfde0 //All 3 lines verify to same &holiday address....great!
(unsigned int*)this = 0x7bfde0
this = 0x7bfde0

1B) Does the "operator ++" create a copy of the object, no because there were no parameters sent to the operator by value or by pointer?

1C) Does the "return *this;" create a copy/clone of the object? Is there a clone somehwere created?

1D) Do all operators HAVE TO have a return value? In this case the compiler seems to understand & reference the holiday object, in that "++day;" in the operator worked & I don't really even need a return to the operator:

operator ++ () {
++day;
return 0;}

And I still get 12/26/2016. Is this bad programming & I should always just put a return in?

1D) return *this;

This means return the value contained in the pointer address....the value of the pointer address of the object, but what values does it REALLY hold? ALL the attributes (variables) values? And maybe a single pointer in there to the 1x copy of the functions?
Also how do I get the address of the location of the pointer &this in code?


QUESTION2:
How is this return possible as one was not specified, does the compiler just put one in?

operator const char*(){......return dateInString.c_str();}

When I manually put a return in, I get a compile error...
const char* operator const char*()



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  #include <iostream>
#include <sstream>
using namespace std;

class Date
{
private:
	int month, day, year;
	string dateInString;
	
public:
	Date (int inMonth, int inDay, int inYear)
		: month(inMonth), day(inDay), year(inYear){}
	
	Date& operator ++ ()
	{
		++day;
		cout << "************************" << endl;
		cout << "(unsigned int*)this = " << (unsigned int*)this << endl;
                //How to get adress of where pointer is stored at?
		//cout << "(&this) = " << &this << endl;	
		cout << "this = " << this << endl;
		cout << "(*this) = " << *this << endl;
		cout << "************************" << endl;
		return *this;		//????????????????????????????
	}
	
	
	void DisplayDate()
	{
		cout << month << "/" << day << "/" << year << endl;
	}
	
	operator const char*()
	{
		ostringstream formattedDate;
		formattedDate << month << "/" << day << "/" << year << endl;
		dateInString = formattedDate.str();
		return dateInString.c_str();
	}
};

int main()
{
	Date holiday (12, 25, 2016);
	cout << "&holiday = " << &holiday << endl;
	holiday.DisplayDate();

	++holiday;
	holiday.DisplayDate();

	
	return 0;
}
Last edited on
operator++ by definition returns ref *this so that the result can be used. This is the pre-inc version.

If operator++(int) is used, the post-inc version, then the result type would be just Date - and not Date&.

Same for operator--() and operator--(int)

eg.
1
2
3
4
const auto nextDay {++holiday};

nextDay.DisplayDate();
holiday.DisplayDate();


should compile and run as expected.


Although usually with a class such as this, operator<< is overloaded.

 
std::cout << holiday << '\n';

Last edited on
fact 1
its like saying (*this).day
this is a pointer to the current object. If that is holiday, then yes, its holiday's pointer.
if its some other variable, its that variable's pointer.

question 1a
Date& operator ++ () {.......return *this;}
^^^^^ not a pointer, not address. this is a REFERENCE. Pointers and references are similar but are not the same things.
have you studied reference parameters to functions yet?
If it were date* you could return this directly: both would be pointers.

you can assign an array to a pointer. A pointer is *variable* that holds an address, and c++ can turn array names into a pointer/address for you. You can't assign an array a pointer, array's pointer is hidden from you. Its not a pointer, its an array, and c++ does NOT do the conversion the other way around (for very good reasons). An array is not a pointer, but a pointer can be made to look and act just like an array --- they are related, but distinct things.

1b no, no copy is made. it is working on this and day, which it already has access to, kind of like global variables, but only within the scope of the class. If you took the *reference* off the function header, it WOULD copy it on the way out when giving the data back to the caller. The compiler may optimize it away, but technically if you had x = y++ then there is a copying into x, but that is outside the ++ operation. you can also just say y++ and no copy is made.

1c) if you understood 1b, you know the answer to this now.

1d) operators have fixed formats, unlike other functions where you can decide what they return. Most of them do return a value. I would have to think about whether any of them do not ... I can't think of any at all right this second. The compiler is smart enough to do nothing if nothing needs to be done. Don't sweat the cpu level stuff just yet. Remember that c++ expresses your ideas in a formal language, it is not the actual cpu instructions, and in the act of translating to cpu language, the compiler gets rid of a lot of wasted operations that c++ may force you to state via its syntax.

if you don't return anything from ++ it should have given a warning. I can't answer if that is OK or not, but I believe it could be undefined behavior, which is bad programming. One of our undefined behavior experts can chime in on that, but really, you should follow the expected format defined for the operators when you overload them. If you want a different action, unfortunately, don't use an operator overload but instead make a void increment() function.

1d final questions...
this holds the address of the variable of the class type for the current variable/instance.
if you have date foo; inside class date, this means pointer to foo. If you have date bar; it means address of bar.
this is the pointer. if you want the address of *this, leave the goofy * off it :) It is just like any other pointer. for date bar; &this is &&bar ... this is &bar, *this is bar right?
what does it really hold? A variable of a class holds all its members, and is little more than a C struct for a standard class. If you have virtual class items, it has extra data for that. I would table this question (its a good one) for now, but you can google around to get the gory details if you really want to know. You don't need to know this usually.

question 2 .. not sure exactly what you are asking.






1
2
3
4
5
operator ++ () 
{
     ++day;
     return 0;
}


When I ran this on Embarcadero it works without warnings, but after both of your comments I just ran it in VS & I do get the warnings now. So it looks like I will have to stick to the nomenclature of what the operators expect for returns & parameters.

The book actually goes into << overloading a few pages down, but I guess they wanted to show us const char* first.

QUESTION 1a
I know references to be true aliases & if you change the value of the reference you change the value of the original value being referenced:

1
2
3
4
int num1 = 5;
int& ref1 = num1;
ref1 = 99;
cout << ref1 << endl;  //outputs 99 


But I guess I assumed references allocate memory & hold the same address as the address of num1 from above. And changing the value would be a 2 step process behind the scenes. Otherwise how would the program know where to refer to your reference names....unless during compile time wherever the program sees a reference it replaces it with num1 & then no need for memory allocation? Compiler must treat it like the const or constexpr are treated? Is that the way it works?

If that is the way it works, then both "this" and "*this" make more sense within the context of the sample program now.


cout << this; //Which yields 0x7bfde0, address of &holiday is equivalent to ptrNum1 from below.
And "*this" is equivalent to *ptrNum1 from below.

1
2
3
4
5
int num1 = 5;
int* ptrNum1 = &num1;
cout << ptrNum1 << endl;  //Gives the address of num1
cout << *ptrNum1 << endl;  //Gives the 5 value
cout << &ptrNum1 << endl; //Gives the address of where the pointer is stored at 


Still curious how to get the &ptrNum1 equivalent for &this though...address where pointer is stored?

QUESTION 2:
1
2
3
4
5
6
7
operator const char*()
	{
		ostringstream formattedDate;
		formattedDate << month << "/" << day << "/" << year << endl;
		dateInString = formattedDate.str();
		return dateInString.c_str();
	}


Functions return values & if no return then still need to use void, but operator const char*() does not specify a return_type name & no void before the "operator" keyword. I thought that if you are returning a const char* it should be as follows:

const char* operator const char*(){}

Last edited on
No. For these operators, the return type is automatically set to the specified cast type so isn't specified.
So to understand that, I have to know about casting? I have not covered that chapt yet, much further down the line.

All I know now is that these operators are in the following syntax:
return_type operator operator_symbol { possible parameters}

So the following 2x options, but not one without anything (empty) before keyword "operator".
void operator or
return_type operator
Last edited on
But I guess I assumed references allocate memory & hold the same address as the address of num1 from above.

You can't be sure. In the CPU code, everything is an address. Variable names are just human readable addresses, at the end of the day.
if you say
int x{3};
int &y = x;
y = 42;
cout << x;
the computer cpu sees something akin to:
move 3 to address 1234
move 42 to address 1234
cout data at address 1234

does that help with "this" pointer?


Still curious how to get the &ptrNum1 equivalent for &this though...address where pointer is stored?

date foo; //foo has an address. it is &foo.
inside date class:
this //address of foo, same as &foo
&this ... address of the address of foo. I am not sure how meaningful that value is.
&&foo as above, foo side

casting is really simple. You just define a cast from your class to whatever other type. After one or 2 small examples you will know all you need on those for a while. You may revisit it with polymorphism later.
Yes, it all fits into place now & makes sense thanks to your & others feedback.

When I add this "cout << "&this = " << &this << endl;" line to "operator ++()", I get this error. And I tried "&(this)" and "(&this) as well.


[Error] lvalue required as unary '&' operand
This is a pointer to an instantiated class, so is an address. So you don't need the &.
Ah, nevermind. The compiler is right, you can't go back that far. At some point your pointer chain is not stored in any variables, so there is no address to back up into.

int x; //x is created and has an address
cout << &x; //ok, x has an address
cout << &&x; //not ok. you can't back up that far, &x is not stored in memory and has no address. Same for &this, it is nonsense... my mistake, I did not think through the memory chains earlier. You can't take the address of something that does not have one!

but as I did note, there is no real use for &this anyway.
Last edited on
Hmmmm, but don't all pointers have addresses though? Is the "this" pointer of a class a pseudo pointer or works in another way? Again maybe.... the compiler replacing "this" for the address of the object every time it sees it during compile time & no new address location needs to be stored in memory?

I understand now though that it is not important & no real reason to use it though.

One other thing that you just reminded me of what I saw in the book & now just use it, but don't know WHY it is this way. When learning about the referencing & dereferencing I was content when it came to simple variables, but then pointers to char arrays came in & changed the initial rules.

1
2
3
int num1 {5};
int* ptrNum1 = &num1;
cout << ptrNum1 << endl; //Gets the address of num1 (&num1) 


"ptrNum1" prints the address location of num1 (&num1), but when creating a pointer to an array printing out "pointer" from the code below prints out the entire contents of the array & NOT the address of the array.

I also assumed that when I request this "&myString[0]" to also be able to get the address where array index 0 is & I was shocked that it output the entire array. I then wrote the following to help me decipher and it seems like it is saying starting at that index get me the rest of the values in the array...which totally came out of left field.

Most likely they changed the rules because they needed pointers of arrays to be able to also be accessed like an array for coding convenience. I also understand that pointers can use index just like arrays & arrays can use dereference operators. I guess I have no choice but to accept these new findings, learn them & not make mistakes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
using namespace std;

int main()
{
	int num1 {5};
	int* ptrNum1 = &num1;
	cout << &num1 << endl;
	cout << ptrNum1 << endl;
	cout << "**************************" << endl;


	char myString[4]= {'y', 'e', 's', '\0'};
	
	cout << "myString = " << myString << endl;			//="yes"
	cout << "myString[0] = " << myString[0] << endl;		//="y"
	cout << "&myString[0] = " << &myString[0] << endl;	//="yes"  ???????
	cout << "&myString[1] = " << &myString[1] << endl;	//="es"  
	cout << "&myString[2] = " << &myString[2] << endl;	//="s"  
	cout << "&myString = " << &myString << endl;		//="0x7afe1c" myString[0]
	cout << "&myString + 1 = " << &myString + 1 << endl;	//="0x7afe20" myString[1]
	cout << "&myString + 2 = " << &myString + 2 << endl;	//="0x7afe24" myString[2]
	cout << "**************************" << endl;

	char* pointer = myString;

	cout << "pointer = " << pointer << endl;		//="yes"
	cout << "*pointer = " << *pointer << endl;		//="y"
	cout << "pointer[0] = " << pointer[0] << endl;	//="y"
	cout << "&pointer = " << &pointer << endl;	//="0x7afe10" pointer address
	cout << "&pointer[0] = " << &pointer[0] << endl;	//="yes"
	cout << "&pointer[1] = " << &pointer[1] << endl;	//="es"
	cout << "&pointer[2] = " << &pointer[2] << endl;	//="s"
	
	//="0x7afe1c"  address of myString[0]
	cout << "(unsigned int*)pointer = " << (unsigned int*)pointer << endl;
	
	//="0x7afe20" address of myString[1]
	cout << "(unsigned int*)pointer + 1= " << (unsigned int*)pointer + 1 << endl;
	
	//="0x7afe24" address of myString[2]
	cout << "(unsigned int*)pointer + 2= " << (unsigned int*)pointer + 2 << endl;
	
	return 0;
}


Now the real question is how the heck do the 2 lines of code below give you an address?
"(unsigned int*)pointer "
"cout << (unsigned int*)buffer << endl;"

Why doesn't the compiler just let me use a version of "&" to get the pointed to address with arrays? Is there another way to get the pointed to address with "pointer" & "buffer" from the two lines........
"&(*pointer)" does not work
"&*pointer" does not work!

"cout << (unsigned int*)buffer << endl;"
What does that line say, take the value of buffer & send it to a temporary unsigned int pointer, so it can have more storage space..........and then magically give me the address....how?
Last edited on
char* is treated differently - the exception to the rule. This is assumed to be a pointer to a null terminated c-style string - so cout treats this as a null-terminated string pointer and displays all the chars to the null terminator character. if you don't want this behaviour, cast the pointer to void*.

Yes, I mean to say char arrays & not just any arrays when I seem to refer to them as regular arrays. Regular arrays stick to the rule & all of a sudden char arrays don't play by them.
Thanks I will keep the cast void* in mind as I am doing the cast chapter right after I finish the operator chapt.
Hmmmm, but don't all pointers have addresses though?

No.
int x;
&x does not require an address. If you think about it, they have to stop somewhere, else you would run out of ram to talk about the address of the address of the address of the address of x...

'this' is mostly a normal constant pointer. It is a keyword and its setup and management are all hidden from you, but at the end of the day, its just a pointer.

the compiler replacing "this" for the address of the object every time it sees it during compile time & no new address location needs to be stored in memory?
That is exactly what happens! But the exact same thing happens in the case of &x above too (and in my earlier &&x does not work example) . And the exact same thing is really how references work. The behavior is not unique to 'this'.

the special behavior of char* is a constant headache. But it is what it is for C compatibility and legacy code and backwards compatibility reasons.

Why doesn't the compiler just let me use a version of "&" to get the pointed to address with arrays?

it will.
int x[10];
int *px = x; //pointer to the array, language does the work for you
int *px5 = &x[5];
you don't need &&x and that is just like the above, it does not explicitly exist in memory, and you can't get its address.
there are some ugly hacks you can do, eg you can cast int x[100] int to a 2-d 10x10 entity, but you run into the array "compile time constant" problem ... its not doable in general where the dimensions are variable, only if they are constants at compile time.

"cout << (unsigned int*)buffer << endl;"
you are trying too hard. This is just a C style cast, it says "cast buffer to a pointer" and you cout the address you get from that. Casting is not making a pointer -- you had to have the pointer already, whether it is an array name or something else.
&(*type) is back to the && x problem.

You almost have it. Go back to the 'the compiler puts the address in for the variable' concept. That is the key to all these questions (apart from the char* anomaly).

Another thing that may help you to see it... think about what you are trying to DO. What problem do you want to solve with &&X code? How would the compiler resolve it (see the infinite chain above)? If you can state the problem you want to solve, we can show you how to do it, and you will see how to work around the 'limitation' of not being able to chain &&&& past where there actually exists an address. It is not a limitation that causes much trouble, because you simply do not need it. If some function takes a triple pointer, the way to get it is NOT to feed it the &&& of some variable, it is to craft the correct triple *** structure and set it up for the function's usage.
Last edited on
Topic archived. No new replies allowed.