admin管理员组文章数量:1129439
I have a question regarding the arrow operator's overload process. The overloading makes it seem like it is a unary operator, while the usage makes it appear as a binary operator. The return value isn't intuitive either. Only a raw pointer is returned.
#include <iostream>
template <typename T>
class Auto_ptr1
{
T* m_ptr {};
public:
// Pass in a pointer to "own" via the constructor
Auto_ptr1(T* ptr=nullptr)
:m_ptr(ptr)
{
}
// The destructor will make sure it gets deallocated
~Auto_ptr1()
{
delete m_ptr;
}
// Overload dereference and operator-> so we can use Auto_ptr1 like m_ptr.
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
};
// A sample class to prove the above works
class Resource
{
public:
Resource() { std::cout << "Resource acquired\n"; }
~Resource() { std::cout << "Resource destroyed\n"; }
void sayHi() { std::cout << "Hi!\n"; }
};
void someFunction()
{
Auto_ptr1<Resource> ptr(new Resource()); // ptr now owns the Resource
int x;
std::cout << "Enter an integer: ";
std::cin >> x;
if (x == 0)
return; // the function returns early
// do stuff with ptr here
ptr->sayHi();
}
int main()
{
someFunction();
return 0;
}
In the example ptr->sayHi(), one might expect the entire expression ptr-> to be replaced with the raw pointer, but apparently, only ptr is replaced. Anything that follows is coherent with intuition. The intermediate step is what bugs me. Is the overloading process of the arrow operator an exceptional case?
It's just a theory question.
I have a question regarding the arrow operator's overload process. The overloading makes it seem like it is a unary operator, while the usage makes it appear as a binary operator. The return value isn't intuitive either. Only a raw pointer is returned.
#include <iostream>
template <typename T>
class Auto_ptr1
{
T* m_ptr {};
public:
// Pass in a pointer to "own" via the constructor
Auto_ptr1(T* ptr=nullptr)
:m_ptr(ptr)
{
}
// The destructor will make sure it gets deallocated
~Auto_ptr1()
{
delete m_ptr;
}
// Overload dereference and operator-> so we can use Auto_ptr1 like m_ptr.
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
};
// A sample class to prove the above works
class Resource
{
public:
Resource() { std::cout << "Resource acquired\n"; }
~Resource() { std::cout << "Resource destroyed\n"; }
void sayHi() { std::cout << "Hi!\n"; }
};
void someFunction()
{
Auto_ptr1<Resource> ptr(new Resource()); // ptr now owns the Resource
int x;
std::cout << "Enter an integer: ";
std::cin >> x;
if (x == 0)
return; // the function returns early
// do stuff with ptr here
ptr->sayHi();
}
int main()
{
someFunction();
return 0;
}
In the example ptr->sayHi(), one might expect the entire expression ptr-> to be replaced with the raw pointer, but apparently, only ptr is replaced. Anything that follows is coherent with intuition. The intermediate step is what bugs me. Is the overloading process of the arrow operator an exceptional case?
It's just a theory question.
Share Improve this question asked Jan 8 at 9:04 user29104083user29104083 112 bronze badges New contributor user29104083 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 8 | Show 3 more comments2 Answers
Reset to default 2Yes, the arrow operator is an exceptional case of sorts. This is because the built-in ->
operator is itself an exceptional case. For all other binary operators, the arguments are expressions that designate objects, so x ⊕ y
means the same as x.operator⊕(y)
(⊕ is any non-exceptional binary operator).
In x->y
however, y
is not an object, but an identifier that designates a class member. One cannot pass such a thing as a parameter to a user-defined function, x.operator->(y)
would make no sense. So x->y
is made to mean x.operator->()->y
instead, in order for x
to behave just like a pointer. As a consequence, the overloaded operator->
is required to be unary, not binary.
You can show that it is a unary operator by explicitly calling it:
#include <iostream>
class MyClass
{
public:
int A = 0;
int* operator->() { return &A; };
};
int main()
{
MyClass object;
object.A = 10;
std::cout << "object.A: " << object.A << "\n";
// Explicitly call the -> operator, and de-reference the int pointer that is returned
std::cout << "object->: " << *object.operator->() << "\n";
return 0;
}
Keep in mind that returning a class member is not the normal 'expected' use of a -> operator, this is just for demonstration purposes.
本文标签:
版权声明:本文标题:In C++, is the overloading of the arrow operator an exceptional case or does it follow the same logic as the case for other oper 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736746321a1950794.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
->
). So I don't see a real issue with your code (other than the fact that std::unique_ptr already exists). – Pepijn Kramer Commented Jan 8 at 9:08ptr->sayHi()
. Instead it's equivalent toptr.operator->()->sayHi()
. In other words, theoperator->()
function is called on theptr
object (which isn't a pointer), it returns a pointer to aResource
object, and the pointer is dereferenced to get the actualResource
object and thesayHi()
function is called on thatResource
object. – Some programmer dude Commented Jan 8 at 9:08->
it is considered a unary operator because what appears on the right hand side is not an expression (technically it's an identifier expression, rather than a regular expression). An operator is binary if it combines two regular expressions. – john Commented Jan 8 at 9:43operator->
has special semantics"). Also related: Why overloaded de-reference operator doesn't work the same way as the arrow operator? – JaMiT Commented Jan 8 at 10:21