In ·std::unique_ptr· code in file "memory", I see operator overloading functions as
typename tr1::add_reference<_Ty>::type operator*() const
{
// return reference to object
return (*this->_Myptr);
}
pointer operator->() const
{
// return pointer to class object
return (&**this);
}
What does the &** mean in the second function? Thanks.
this is a pointer to the unique_ptr object.
*this is a reference to the unique_ptr object.
**this is dereferencing the unique_ptr using operator* (i.e. *this->_Myptr).
So, &**this is a pointer to the object pointed at by the unique_ptr (i.e. &(*this->_Myptr)).
As per the posted code, **this is invoking operator* overload which returns a reference to an object. so &**this becomes address of the returned object.
In other words, **this is same as (*this->_Myptr), and &**this is same as &(*this->_Myptr).
Related
I wonder, why don't we use only this without * in case of an overloaded assignment operator? If I use this only, it gives me a compiler error. Why we don't use * with arr[i], or any other variables, like return x in the 2nd and 3rd example?
Myclass &Myclass::operator=(const Myclass &rhs)
{
if(this==&rhs)
return *this;
}
double& setValues( int i ) {
return vals[i]; // return a reference to the ith element
}
int& setValues(int x) {
return x; // return address/reference of x
}
#logan_92: References, and pointers are a bit tricky: House& is a reference to a house somewhere ("That is Bob's house over there"). House* is a building address ("13931 Main Street"). Dereferencing a pointer is like driving to the building.
Likewise: this is a pointer. It is the address of a Myclass, it is not a Myclass itself. operator= returned a reference to a house, so you dereference it to go to the Myclass&, so that you can return the reference. It has nothing to do with being "inside the class" or "outside the class". The only difference is an address vs a reference.
One of the things you can do with pointers and addresses is get an offset. ("The house 3 down from 13931 Main Street"). The basic syntax is *(pointer+3). This turns out to be incredibly handy, so C made a special syntax for this: pointer[3]. It is a reference to the third object over from the address of pointer. As a result, this[0] is the same as *this. It's 0 objects over from the address.
I have a class whose objects have to pass a reference to themselves to another function.
I discovered that this is a pointer, not a reference. So how do I get the reference to the object that I'm in?
You can get an l-value of yourself to return as a reference by dereferencing the this pointer ie:
return *this;
Since this is a pointer to the object, you can get the object itself by derefrencing it with *this.
The function :
void func(MyClass& obj)
{ }
Calling the function.
func(*this);
I have code where I am trying to pass the underlying pointer of a unique_ptr in to a method accepting a pointer by reference:
unique_ptr<A> a;
func(a.get());
to call:
void func(A*& a){ // I am modifying what `a` points to in here
}
but I am getting compiler errors because get() is not returning what I expected was just the raw pointer. Is it possible to achieve what I am trying to do here?
No, and that's a good thing.
The problem is that get() returns an rvalue, not a reference to unique_ptr's internal pointer. Therefore you can't modify it. If you could, you would completely mess up unique_ptr's internal state.
Just pass a reference to the unique_ptr itself if you want to modify it.
A function that takes a pointer by reference is strongly hinting that it may reallocate/delete the pointer in question. That means it is asking for ownership responsibilities. The only safe way to call such a function is to release the pointer from the unique pointer and (possibly) reacquire it after the call.
// a currently manages (owns) the pointer
std::unique_ptr<A> a;
// release ownership of internal raw pointer
auto raw = a.release();
// call function (possibly modifying raw)
func(raw);
// (re)claim ownership of whatever func() returns
a.reset(raw);
But that can still be problematic if (say) the unique_ptr has a special deleter and the function doesn't re-allocate the object accordingly. Also if the function deletes the pointer without setting it to nullptr you will have a problem.
Here is an idea:
template<typename T> struct raw_from_ptr {
raw_from_ptr(T& pointer) : _pointer(pointer), _raw_pointer(null_ptr) {}
~raw_from_ptr() {
if (_raw_pointer != null_ptr)
_pointer.reset(_raw_pointer);
}
raw_from_ptr(pointer_wrapper&& _other) : _pointer(_other._pointer) {
std::swap(_raw_pointer, _other._raw_pointer);
}
operator typename T::pointer*() && { return &_raw_pointer; }
operator typename T::pointer&() && { return _raw_pointer; }
private:
T& _pointer;
typename T::pointer _raw_pointer;
};
template<typename T> raw_from_ptr<T> get_raw_from_ptr(T& _pointer) {
return raw_from_ptr<T>(_pointer);
}
Usage:
unique_ptr<A> a;
func(get_raw_from_ptr(a));
this is a pointer to the calling object (it returns the r-value).
*this is a pointer to the pointer of the calling object (it returns the value of the address).
**this is a pointer to the pointer of the pointer of the calling object (???).
&***this is a reference to the pointer of the pointer of the pointer of the calling object (???).
std::vector<int>:: iterator i = vector1.begin();
i is the pointer to its own r-value (returns its own value).
*i is the pointer of a r-value of an object contained in a vector (returns the value pointed in &value).
**i is the pointer to the pointer of a r-value of an object contained in a vector (???).
I am really confused.
Here's a sample code where we find the expression &**this:
class _Iter
{
private:
ListElem *pCurr;
const List *pList;
public:
_Iter(ListElem *pCurr, const List *list)
: pCurr_(pCurr), pList(list)
{}
T& operator*() { return pCurr_->data; }
T* operator->() { return &**this; }
};
this is a pointer to the current object.
*this is a reference to the current object, i.e. this dereferenced.
**this is the returned value of the overloaded unary operator* function called on the current object.
If the object returned from **this has an overloaded operator&() function, then &**this evaluates to the returned value of (**this).operator&(). Otherwise, &**this is the pointer to the returned value of the overloaded unary operator* function called on the current object.
Example:
#include <iostream>
struct A
{
int b;
int a;
int& operator*() {return a;}
int* test()
{
return &**this;
}
};
int main()
{
A a;
std::cout << "Address of a.a: " << a.test() << std::endl;
std::cout << "Address of a.a: " << &(*a) << std::endl;
std::cout << "Address of a.a: " << &(a.a) << std::endl;
return 0;
}
Sample output:
Address of a.a: 0x7fffbc200754
Address of a.a: 0x7fffbc200754
Address of a.a: 0x7fffbc200754
If you have a class Foo and a method of this class that use this and the object Foo obj then
this - is a value of type pointer to Foo that has a value of address of object obj
so you can write like this (for example in Foo:test()):
Foo *addr = this;
so addris a variable of type pointer to Foo that is initialized with a address value of object obj of class Foo.
All pointers in C++ can be dereferenced with *. So when you dereference a pointer to an object you get that object
Foo *addr = get_pointer_to(obj); //function that return a pointer to object
//three equivalent ways to call someMethod() of object obj of class Foo
obj.someMethod();
addr->someMethod();
(*addr).someMethod();
Upper part of code illustrates that object obj and dereferenced pointer (*addr) have the same syntax, because they are the same object.
C++ allows you to overload different language operators. So when you write (**this) the compiler looks to this and find that this is type of pointer to Foo, so dereferencing *this gives object of type Foo. Then the compiler find (* (*this)). But Foo is not a type of the pointer, so by default there is no * operator. So the compiler will returen an error and break the compilation. But if you define(overload) operator*() in class Foo then the compiler will call this method. So **this is equivalent to this->operator*() or to (*this).operator*().
The last one is operator&(). By default this operator returns a pointer to object. But of course it can be overloaded and return something else.
So &**this can return
1) an address of object that was returned by operator*() applied to the object (*this)
2) return value of method operator&() of the object that was returned by operator*() which was applied to (*this).
If there is no operator*() defined then &**this won't compile.
In addition if there is no operator*() defined and no operator&() defined then the construction of &**some_pointer will either not compile or will return (*some_pointer). And I can guarantee that (*some_pointer) will be a pointer.
I suspect I don't understand something about move semantics. Given the following code I would expect the debugger (MSVC2010SP1) to call Proxy's members in the following order:
Proxy(Resource*) constructing the temporary in getProxy
Proxy(Proxy&& other) move constructing p
~Proxy() destructing the empty shell of the temporary that got its guts taken by move
~Proxy() p goes out of scope
class Resource
{
void open(){}
public:
void close(){}
Proxy && getProxy();
};
class Proxy
{
Resource *pResource_;
Proxy(const Proxy& other); //disabled
Proxy& operator=(const Proxy& other); //disabled
public:
Proxy(Resource *pResource):pResource_(pResource){}
Proxy(Proxy&& other):pResource_(other.pResource_){other.pResource_ = nullptr;}
~Proxy()
{
if(pResource_)
pResource_->close();
pResource_ = nullptr;
}
};
Proxy && Resource::getProxy()
{
open();
return Proxy(this);
}
//somewhere else, lets say in main()
Resource r;
{
auto p = r.getProxy();
} // p goes out of scope
Instead the order is:
Proxy(Proxy*)
~Proxy() //this already calls close() earlier than expected
Proxy(Proxy&& other) //moving after destruction gives p.pResource_ a value of nullptr
~Proxy() //p goes out of scope
This makes no sense to me. What I'm trying to do is track the lifetime of the proxy class passing the job of closing the resource via the move constructor from one object to another.
getProxy() returns a reference to a temporary, which goes out of scope at function end and results in a dangling reference.
Returning by rvalue reference doesn't actually cause anything to be moved. It just returns by reference. However, it's different to returning an lvalue reference because an expression calling a function that returns an rvalue reference is an xvalue (as opposed to an lvalue). The xvalue (as a subset of rvalue expressions) can then be moved from. If you wanted to move from the returned object of a function returning lvalue reference, you would have to use std::move to make it an rvalue.
You very rarely will want to actually return an rvalue reference. The only vaguely common use for it is to allow a private member of an object to be moved from. If you want an object to be moved when you return it from a function, just return it by value. In your case, if the return type of getProxy was just Proxy, the temporary would be moved from into the returned object and then that would be moved from into p (save for any elision).
As you have it, your temporary object (contructed by Proxy(this)) is destroyed at the end of the return statement - this is the first call of the destructor. The returned reference is now referencing an invalid object and p is constructed by moving from this invalid reference. That gives you undefined behaviour.