How can you assign a value to the pointer 'this' in C++ - c++

In a function, how to you assign this a new value?

You can assign the object this points at:
*this = XY;
But you can't assign the direct value of this:
this = &XY; // Error: Expression is not assignable

You can't.
9.3.2 The this pointer [class.this]
1 In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value
is the address of the object for which the function is called. [...] (emphasis & link mine)
You can modify the object this points to, which is *this. For example:
struct X
{
int x;
void foo()
{
this->x =3;
}
};
The method modifies the object itself, but something like this = new X is illegal.

Long ago, before the first C++ standard has been published, some compiler implementations allowed you to write the following code inside a constructor:
this = malloc(sizeof(MyClass)); // <<== No longer allowed
The technique served as the only way to control allocation of class of objects. This practice has been prohibited by the standard, because overloading of the operator new has solved the problem that used to be tackled by assignments to this.

You can't. If you feel the need to do this perhaps you should be writing a static method taking a class pointer as it's first parameter.

You cannot assign value to this pointer. If you try to assign the value to the this somthing like this = &a it would result in illegal expression

You can not.
"this" is a hidden argument to every member function of a class and its type for an object of Class X is X* const. This clearly means that you can not assign a new vale to "this" as it is defined as a const. You can however modify the value pointed to by this. Refer http://www.geeksforgeeks.org/this-pointer-in-c/ for more details.

Related

Example of lvalues / rvalues yielded by member access operators

I have found multiple questions regarding the lvalue yielded by the arrow operator and the lvalue or rvalue yielded by the dot operator, but the answers are not quite coherent.
Chapter 4.6 of the book C++ Primer says:
The arrow operator requires a pointer operated and yields an lvalue. The dot operator yields an lvalue if the object from which the member is fetched is an lvalue; otherwise, the result is an rvalue.
Does the author only mean data members, or also member functions that can be used as an lvalue? Can someone give me an example where the behaviour of these two operators differs, and explain why that is?
Please excuse me if this has been answered elsewhere.
The quote is much easier to understand with some examples. I'll start with the "dot" operator first.
The "dot" operator
Lets consider data members first with a simple Person example:
struct Person {
std::string name;
};
In general when people use a struct or class, you'll normally see it accessed through a named-value which will always yield the standard/expected lvalue reference:
auto person = Person{"Foo"}
std::string& name = person.name;
However, this doesn't always have to be an lvalue. This member access through the "dot" operator will propagate the refness of the object being accessed. That means that you can implicitly get an rvalue ref of name if person is an rvalue (XValue):
auto person = Person{"Foo"};
std::string&& name = std::move(person).name;
Try it Online
or as a temporary (PRValue):
// Note: using a function call here so that the reference doesn't dangle
auto consume(std::string&&) -> void;
...
consume( Person{"Foo"}.name );
Try it Online
This is what the quote is referring to when it says:
The dot operator yields an lvalue if the object from which the member is fetched is an lvalue; otherwise, the result is an rvalue.
This value-propagation is somewhat true of member functions as well. Since C++11, it's been possible to ref-qualify member functions -- which will call the appropriate function based on the refness of the underlying object:
class Person {
...
auto get_name() && -> std::string&&;
auto get_name() const & -> const std::string&;
...
private:
std::string m_name;
};
...
auto person = Person{...};
person.get_name(); // calls 'get_name() const &'
std::move(person).get_name(); // calls 'get_name() &&'
Try it Online
Note: Unlike accessing a data member, the result of the function call need not actually match the value-category; this is just used for determining which function to call as a form of overload resolution.
Arrow Operator
For the default arrow operator (e.g. not a custom operator->), it can only operate on pointers. Pointers, unlike references, don't contain the underlying value-category of the pointee; they only know the value category of the pointer itself.
For example, std::moveing a Person* will yield a Person*&& -- which is an rvalue of the pointer, but not of the underlying pointed object. For this reason, dereferencing through operator-> can never yield an rvalue, since the pointee is never known to be an rvalue.
Custom operator-> definitions
The Arrow operator is also interesting because, for a custom class, it can be overloaded by defining operator->() -- but this operator will still be constrained by the same problem as described above!
Any definition of operator-> must return an object which either defines operator->, or is a pointer. This is done because any expression a->b in C++ will recursively call operator-> until it reaches a pointer in order to perform the dereference. As we know from above, a pointer does not contain a value category -- so once we reach this point we cannot get an rvalue.
Even if you were to attempt to combine this with ref-qualified functions, such as:
auto operator->() && -> SomeWrapper<T>;
you still won't be able to propagate the value-category to the reference because eventually it will come back down to a pointer which does not contain a value category.
Preface: the C++ system of value categories is rather abstruse; the terms 'lvalue' and 'rvalue' really aren't the whole story, so if you want the full explanation of value categories in all its technical glory, I advise you to check out https://en.cppreference.com/w/cpp/language/value_category as #Richard Critten said in the question comments.
Now, supposing you have a struct
struct S{
int member {5};
};
, the behaviour of the operators will differ when performing member access on temporary objects—since their addresses cannot be taken, member access can only take the form of the dot operator (since no pointer can be produced for the arrow operator):
int x = S().member; // Ok, x = 5
int x = (&(S()))->member; // Error: cannot take address of temporary object
In this case, S() is an rvalue expression, and we can use the dot operator on it, but there isn't really a way to use the arrow operator on it.
Regarding "member functions that can be used as an lvalue", I'm assuming you mean functions that return an lvalue reference, e.g.
struct S {
int member {5};
int& get_ref()
{
return member;
}
}
where the returned lvalue reference can be written to; I don't believe that there is any functional difference with the normal member access case.

so what is the type of "this" ? Why is "this" not a lvalue?

Say the object is
class A {
public : void Silly(){
this = 0x12341234;
}
I know I will get compiler error ' "this" is not a lvalue.' But then it is not a temporary either. So what is the hypothetical declaration of "this" ?
Compiler : GCC 4.2 compiler on mac.
For some class X, this has the type X* this;, but you're not allowed to assign to it, so even though it doesn't actually have the type X *const this, it acts almost like it was as far as preventing assignment goes. Officially, it's a prvalue, which is the same category as something like an integer literal, so trying to assign to it is roughly equivalent to trying to assign a different value to 'a' or 10.
Note that in early C++, this was an lvalue -- assigning to this was allowed -- you did that to handle the memory allocation for an object, vaguely similar to overloading new and delete for the class (which wasn't supported yet at that time).
It is impossible to provide a "declaration" for this. There's no way to "declare" an rvalue in C++. And this is an rvalue, as you already know.
Lvalueness and rvalueness are the properties of expressions that produce these values, not the properties of declarations or objects. In that regard, one can even argue that it impossible to declare an lvalue either. You declare an object. Lvalue is what is produced when you use the name of that object as an expression. In that sense both "to declare an rvalue" and "to declare an lvalue" are oxymoron expressions.
Your question also seems to suggest that the properties of "being an lvalue" and "being a temporary" are somehow complementary, i.e. everything is supposedly an lvalue or a temporary. In reality, the property of "being a temporary" has no business being here. All expressions are either lvalues or rvalues. And this happens to be an rvalue.
Temporaries, on the other hand, can be perceived as rvalues or as lvalues, depending on how you access the temporary.
P.S. Note, BTW, that in C++ (as opposed to C) ordinary functions are lvalues.
For one thing, this is not a variable - it's a keyword. When used as a rvalue, its type is A * or A const *. In modern C++, assigning to this is prohibited. You cannot take the address of this, either. In other words, it's not a valid lvalue.
To answer the second part, "why is this not an lvalue", I'm speculating as to the committee's actual motivation, but advantages include:
assigning to this doesn't make much logical sense, so there's no particular need for it to appear on the left-hand-side of assignments. Making it an rvalue emphasises that this doesn't make much sense by forbidding it, and means that the standard doesn't have to define what happens if you do it.
making it an rvalue prevents you taking a pointer to it, which in turn relieves the implementation of any need to furnish it with an address, just like a register-modified automatic variable. It could for example devote a register in non-static member functions to storing this. If you take a const reference, then unless the use permits cunning optimization it needs to be copied somewhere that has an address, but at least it needn't be the same address if you do it twice in quick succession, as it would need to be if this were a declared variable.
You get a compiler error because this is a const pointer to the instance of the class of the same type as that class. You can't assign to it although you can use it to change other class members in non-const qualified methods, call methods, and operators. Also note because it's an instance that static methods do not have a this pointer.
Hypothetical:
class Whatever
{
// your error because this is Whatever* const this;
void DoWhatever(const Whatever& obj) { this = &obj; }
// this is ok
void DoWhatever(const Whatever& obj) { *this = obj; }
// error because this is now: const Whatever* const this;
void DoWhatever(const Whatever& obj) const { *this = obj; }
// error because this doesn't exist in this scope
static void DoWhatever(const Whatever& obj) { *this = obj; }
};

What is the meaning of & in c++?

I want to know the meaning of & in the example below:
class1 &class1::instance(){
///something to do
}
The & operator has three meanings in C++.
"Bitwise AND", e.g. 2 & 1 == 3
"Address-of", e.g.: int x = 3; int* ptr = &x;
Reference type modifier, e.g. int x = 3; int& ref = x;
Here you have a reference type modifier. Your function class1 &class1::instance() is a member function of type class1 called instance, that returns a reference-to-class1. You can see this more clearly if you write class1& class1::instance() (which is equivalent to your compiler).
This means your method returns a reference to a method1 object. A reference is just like a pointer in that it refers to the object rather than being a copy of it, but the difference with a pointer is that references:
can never be undefined / NULL
you can't do pointer arithmetic with them
So they are a sort of light, safer version of pointers.
Its a reference (not using pointer arithmetic to achieve it) to an object.
It returns a reference to an object of the type on which it was defined.
In the context of the statement it looks like it would be returning a reference to the class in which is was defined. I suspect in the "Do Stuff" section is a
return *this;
It means that the variable it is not the variable itself, but a reference to it. Therefore in case of its value change, you will see it straight away if you use a print statement to see it. Have a look on references and pointers to get a more detailed answer, but basecally it means a reference to the variable or object...

Regarding address operator C/C++

What does address operator mean.
say in the method below.
what should be passed in the method as parameter value of integer or the address of an integer variable.
void func1(int&)// method declaration
void func1(int& inNumber)//method definition
{
//some code
}
That’s not the address operator – it’s the reference type character. This means that for any type T, T& is a reference to T. It’s an unlucky coincidence that this happens to be the same character as the address operator.
You can pass normal objects to this method. No need to take any further action. Read up on references in your favourite C++ book.
There is no address-of operator in your code - the ampersand is being used to declare a reference. Which C++ text book are you using that does not cover this?
In this case the function takes a reference to an int which is denoted by the int &inNumber.
The function is called as if you were calling it with the value:
int x = 2;
func1(x);
From the perspective of the caller, this looks exactly the same as a pass by value function, though in the case of the reference the function may indeed change the value of x.
That's not an address operator. In a declaration, the & means it's a reference.
You can think of references as pointers that you don't have to dereference.* You can just say inNumber = 5; (instead of *inNumber = 5;) and the effect will be visible outside the function.
* Note: References are not just "pointers that you don't have to dereference". It just helps to think of them in that way, sometimes.
its called as reference in c++
http://en.wikipedia.org/wiki/Reference_(C%2B%2B)

c++ polymorphism ((X*)y)->foo() vs ((X)*y).foo()

Suppose Y is a derived class from class X and X declares foo to be virtual. Suppose y is of type (Y*). Then ((X*)y)->foo() will execute the Y version of foo(), but ((X)*y).foo() will execute the X version. Can you tell me why polymorphism does not apply in the dereferenced case? I would expect either syntax would yield the Y version of foo().
You are slicing the Y object part and copy the object into an X object. The function then called is called on an X object, and thus the function of X is called.
When you specify a type in C++ in a declaration or cast, that is meant to say that the object declared or casted-to is actually of that type, not of a derived type.
If you want to merely treat the object is being of type X (that is to say, if you want the static type of the expression be X, but still want it to denote an Y object) then you cast to a reference type
((X&)*y).foo()
This will call the function in the Y object, and will not slice nor copy into an X object. In steps, this does
Dereference the pointer y, which is of type Y*. Dereferencing yields an lvalue expression of type Y. An lvalue expression can actually denote an object of a derived type, even if its static type is the one of its base.
Cast to a X&, which is a reference to X. That will yield an lvalue expression of type X.
Call the function.
Your original cast did
Dereference the pointer y.
The resulting expression casted to X. This will yield to a copy operation into a new X object. The resulting expression of that is an rvalue expression of static type X. The dynamic type of the object denoted is also X, as is with all rvalue expressions.
Call the function.
A cast always(*) creates a new object of the type you're casting to, which is constructed using the object you're casting.
Casting to X* creates a new pointer (that is, an object of type X*). It has the same value as y, so it still points to the same object, of type Y.
Casting to X creates a new X. It is constructed using *y, but it otherwise has nothing to do with the old object. In your example, foo() is called on this new "temporary" object, not on the object pointed to by y.
You are correct that dynamic polymorphism only applies to pointers and references, not to objects, and this is the reason why: if you have a pointer-to-X then the thing it points to might be a subclass of X. But if you have an X, then it's an X, and nothing else. virtual calls would be pointless.
(*) unless optimisation allows the omission of code that doesn't change the result. But optimisation isn't allowed to change what foo() function is called.
The dereferencing (the *y part) is fine, but the cast (the (X) part) creates a new (temporary) object specifically of class X -- that's what casting means. So, the object has to have the virtual table from class X -- consider that the casting will have removed any instance members added by Y in the subclassing (indeed, how could X's copy ctor possibly know about them?), so it would potentially be a disaster if any of Y's overrides were to execute -- secure in their knowledge that this points to an instance of Y, complete with added members and all... when that knowledge was false!
The version in which you cast pointers is of course completely different -- the *X has just the same bits as the Y*, so it's still pointing to a perfectly valid instance of Y (indeed, it's pointing to y, of course).
The sad fact is that, for safety, the copy ctor of a class should really only be called with, as argument, an instance of that class -- not of any subclass; the loss of added instance members &c is just too damaging. But the only way to ensure that is to follow Haahr's excellent advice, "Don't subclass concrete classes"... even though he's writing about Java, the advice is at least as good for C++ (which has this copy ctor "slicing" problem in addition!-)
I believe that's simply due to the way the language is specified. References and pointers use late binding wherever possible, while objects use early binding. It would be possible to do late binding in every case (I imagine), but a compiler that did that wouldn't be following the C++ specifications.
I think Darth Eru's explanation is correct, and here is why I think C++ behaves that way:
The code (X)*y is like creating a local variable that is of type X. The compiler needs to allocate sizeof(X) space on the stack, and it throws away any extra data included in an object of type Y, so when you call foo() it has to execute the X version. It would be difficult for the compiler to behave in a way that would let you call the Y version.
The code (X*)y is like creating a pointer to an object, and the compiler knows that the object pointed to is X or a subclass of X. At runtime when you dereference the pointer and call foo with "->foo()" the class of the object is determined and the proper function is used.