While I was defining the working of an overloaded new operator declared in a class,
I came across following confusion....
HERE ,the return type of the function is 'void',yet I
have to introduce a return statement.....otherwise my program crashes....why so?
What is meant by "void *p"
void *myclass::operator new(size_t size)
{
void *p;
p=malloc(size);
cout<<"IN overloaded new";
if(!p)
{
bad_alloc ba;
throw ba;
}
return p;
}
to the point clarifications are appreciated.
The return type of the function is not void, its a void* (void pointer). A void pointer is a generic pointer which can point to anything, but it cannot be dereferenced - you have to cast it to another type prior to dereferencing it.
If you don't return the void *, then you're not returning the pointer to the memory you allocated, and the users code will fail.
void* is an untyped pointer. It's a pointer that can point to anything. Note that the return type of this function is not void but void*. It's supposed to return a pointer to the memory that was allocated.
Simple demonstration of overloaded new
void* operator new(size_t num)
{
return malloc(num);
}
The return type of the overloaded new must be void*. It is expected to return a pointer to the beginning of the block of memory allocated.ie Here it is returning void * and not void(which means doesnt return anything) .
Related
So I think I might be overthinking this but I wanted to know if someone could clarify why the following statement works in the given code
f->hello();
This is the code
struct bar
{
void hello()
{
std::cout << "Hello World";
}
};
struct foo
{
bar* f;
foo() {
f = new bar();
}
~foo() {
delete f;
}
bar* operator->() {
return f;
}
};
int main()
{
foo f;
f->hello(); //Works
}
Since the following code from above returns a pointer
bar* operator->() {
return f;
}
should'nt
f->hello(); actually be f->->hello();
why does f->hello() work and f->->hello() fails ?
The reason i am thinking that f->->hello() should work is because
f->ptrReturned->hello();
If we overload the -> operator are we required to return a ptr type ? Form what I have tried it seems returning an object type is not allowed
Your understanding is correct basically, but ->-> is not valid syntax. You can use the overloaded operator-> like
f.operator->()->hello();
//^^^^^^^^^^^^ return the pointer
// ^^^^^^^^^ call hello() on the returned pointer
f->hello() is treated as the same of f.operator->()->hello(); that makes the usage of class with overloaded operator-> (e.g. smart pointers) consistent with built-in pointers. The usage would be more natural, and could be used with raw pointers in more general context like templates.
And,
If we overload the -> operator are we required to return a ptr type ?
There're some restrictions:
The overload of operator -> must either return a raw pointer, or return an object (by reference or by value) for which operator -> is in turn overloaded.
Apparently, that's just how an overloaded operator-> works. The part before the -> (not including the operator itself) gets replaced with the return value of the overloaded operator. For example, std::unique_ptr::operator-> returns a pointer, which then gets dereferenced by the ->.
As the example given below, overloaded operator new is returning void pointer
void* Myclass::operator new(size_t size)
{
void *storage = malloc(size);
if(NULL == storage) {
throw "allocation fail : no free memory";
}
return storage;
}
But my calling like this MyClass *x = new MyClass;.
So the question is how that new operator knows that which type of pointer in its left hand side. to be typecasted.
Question 2: What happen if I write MyClass *ptr = new Derived();? it is necessary to overload new operator in both derived as well as in base class?
When you write new MyClass then the compiler knows you are allocating an instance of MyClass and do whatever is needed to handle the allocation, like looking up an overloaded new operator in the class, and do the "type casting".
And in the overloaded operator function you know that it has been called when allocating a MyClass object.
noGiven a private Member pData
private:
T* pData; // Generic pointer to be stored
Below is the overloaded implementation of * and ->
T& operator* ()
{
return *pData;
}
T* operator-> ()
{
return pData;
}
We call the same from the main as shown below:
void main(){
SP<PERSON> p(new Person("Scott", 25));
p->Display();
}
I cannot understand how -> and "*" operator overloading will work here?
or to be more clear how p->Display(); will be interpreted?
The -> operator is special. When it returns an object, it is automatically applied again. If it returns another object it is also applied again, until finally a plain pointer is returned. This is called chaining, the plain pointer is finally dereferenced and the chain stops.
p->Display() is therefore interpreted like this:
p->Display(); // Compiler sees this
T* tmp = p.operator->(); // First applied operator-> (the one you provided)
tmp->Display(); // since T* is a pointer itself, operator-> (the built-in one for pointers) is applied
I have a point in my mind which I can't figure out about new operator overloading.
Suppose that, I have a class MyClass yet MyClass.h MyClass.cpp and main.cpp files are like;
//MyClass.h
class MyClass {
public:
//Some member functions
void* operator new (size_t size);
void operator delete (void* ptr);
//...
};
//MyClass.cpp
void* MyClass::operator new(size_t size) {
return malloc(size);
}
void MyClass::operator delete(void* ptr) {
free(ptr);
}
//main.cpp
//Include files
//...
int main() {
MyClass* cPtr = new MyClass();
delete cPtr
}
respectively. This program is running just fine. However, the thing I can't manage to understand is, how come new operator can be called without any parameter while in its definition it has a function parameter like "size_t size". Is there a point that I am missing here?
Thanks.
Don't confuse the "new expression" with the "operator new" allocation function. The former causes the latter. When you say T * p = new T;, then this calls the allocation function first to obtain memory and then constructs the object in that memory. The process is loosely equivalent to the following:
void * addr = T::operator new(sizeof(T)); // rough equivalent of what
T * p = ::new (addr) T; // "T * p = new T;" means.
(Plus an exception handler in the event that the constructor throws; the memory will be deallocated in that case.)
The new-expression new MyClass() is basically defined in two steps. First it calls the allocator function, which you have overloaded, to get some allocated memory. It passes the size of the type MyClass to that allocator function, which is why the size_t argument is required. After this, it constructs an object in that allocated memory and returns a pointer to it.
The compiler knows the size of your class. Basically, it's passing sizeof(MyClass) into your new function.
So far to my understanding, when defining a pointer variable, we are allocating space in RAM for that variable.
int *p;
Would define a space in RAM. Then we assign a memory address to that pointer using `&variable'.
I'm looking over at an example on: *this vs this in C++
The code is:
#include <iostream>
class Foo
{
public:
Foo()
{
this->value = 0;
}
Foo get_copy()
{
return *this;
}
Foo& get_copy_as_reference()
{
return *this;
}
Foo* get_pointer()
{
return this;
}
void increment()
{
this->value++;
}
void print_value()
{
std::cout << this->value << std::endl;
}
private:
int value;
};
int main()
{
Foo foo;
foo.increment();
foo.print_value();
foo.get_copy().increment();
foo.print_value();
foo.get_copy_as_reference().increment();
foo.print_value();
foo.get_pointer()->increment();
foo.print_value();
return 0;
}
I don't understand what the purpose of putting the * operator in front Foo* get_copy() and Foo* get_pointer() does. Why do I get an error if I removed the * from the Foo* functions while returning this not *this?
edit:
Also, why is:
foo.get_copy().increment();
foo.print_value();
yielding 1 not 2?
I don't understand what the purpose of putting the * operator in front Foo* get_copy() and Foo* get_pointer() does
Foo* get_pointer()
Foo* is a pointer that points to Foo object.
this is also a pointer that implicitly bind to the calling object of the member function. That's why the return type of those functions are Foo* not Foo.
The * is part of the type. So int means type int, and
int* type pointer to int. If the function returns pointer
to int, it is int* foo(), and if it retu rns a pointer to
Foo, it is Foo* Foo::get_pointer().
The definition reserves space for the defined object. A
declaration doesn't reserve any space, and definitions of things
that aren't objects (e.g. references or functions) don't reserve
any space either, at least not that you can see. (Obviously, a
function does exist somewhere in memory, and in many cases, the
compiler will need space as well for its implementation of a
reference. But they are invisible within the scope of C++.)
this, is always a pointer in C++, though you don't mention it explicitly anywhere. So while returning a this pointer, should use Foo*
this is actually an implicit object passed during function call, which is a pointer to the object which calls the function
It seems that you have changed the code from the example that you refer to so that get_copy() no longer returns a copy.
There are 2 ways of using * in your code example. One is for type declaration and the other is the dereferencing operator.
First the type declarations:
int *p means declaring p as a variable of type "pointer to an int".
Foo *get_pointer() means that the function get_pointer will return a value of type "pointer to a Foo object".
Now the dereferencing:
*p means "the value that p points to".
int a = 42;
int *p; // p is of type "pointer to an int"
p = &a; // set p to the address of a (p now "points to" a)
a = 117; // change the value of a
int x = *p; // set x to the value that p points to (which is a) - x will be 117
this is just a pointer to the object. *this means "the object that this points to". In your example this is of type Foo* (pointer to a Foo object) while *this is of type Foo (a Foo object).
"this" is a pointer.
you want to return a pointer to the instance (a specific allocated object).
Foo* get_pointer(){
return this;
}
or you want to return a pointer to the copy, allocate a new object.
//need to implement the copy here
Foo* get_copy(){
return this;
}
and not to the reference (address of the instance). this is why you need to return the pointer.