i have this class called MemoryManager,
it is supposed to implement a simple smart pointer, (count reference);
i have a vector where i store the requested pointers,and i return the index of the pointer to the caller..
when a user creates a pointer of type MemoryManager he calls an initializer function called modified_malloc(size_t) , create a MemoryManager obj, alloc a memory space and store it into data,increase count, and store the object into global_MM_vecotr , and return the index as a pointer , when the use tries to use indirection ( ->) i return the appropriate real pointer from the vector, according to the index value..
class MemoryManager
{
public:
//operators overloading prototypes
private:
void* data;
int count ;
};
std::vector<MemoryManager*> global_MM_vecotr;
void* MemoryManager::operator=( void* x)
{
// some code here
}
the problem i am facing is that i overloaded a couple of operators, however when i try to run the code below the "=" operator doesn't get called..
can some1 point the problem out to me..
//the main code
{
MemoryManager* obj1 = (MemoryManager*) x->fun1(4); //fun1 returns an index to a MemoryManager obj in a vector;
MemoryManager* obj2 = obj1 ;
}
Edit: already tried the following , no change
{
MemoryManager*obj1 = (MemoryManager*) x->fun1(4); //fun1 returns an index to a Class obj in a vector;
MemoryManager*obj2 ;
*obj2 = *obj1;
}
{
MemoryManager* obj1 = ( MemoryManager*) x-> fun1(4);
MemoryManager* obj2;
obj2.operator =(*obj1);
}
From you code, you have defined operator= for the MemoryManager class taking a void* .
Your example code is initializing ClassA pointers and not assigning to MemoryManager instances.
There are three reasons why your code is not being called.
You are initializing not assigning, so if anything a constructor would be called rather than an assignment operator.
You are initializing pointers and not objects, pointers are basic types and you cannot provide overloaded operators for them.
You are using ClassA and not MemoryManager which you have actually provided the operator= for.
See spec, you cannot override pointer basic operations.
Might be a technicality, but you're not assigning a ClassA, you're assigning a ClassA* (ie, a pointer). I might be way off here, but this is where I'd lay the blame.
I suspect you're using the void pointer so that you can enter any kind of object. I'd recommend using a template instead combined with the boost::check library.
Related
I've seen a few places that show how to overload the global new function for allocations. What I would like to do is to have any call to 'new' call my function, which simply wraps the C++ standard 'operator new' and tracks memory usage. But I have a problem of not knowing how to construct the object because the type of the object is not available in the function:
void* operator new (std::size_t size)
{
// I don't know what to construct
}
struct MyClass{ int members[8];}
new MyClass; // I'd basically like to wrap the standard 'new' function allocator.
You are not supposed to construct an object inside of an overloaded operator new, only allocate raw memory of the requested size and return a pointer to it. The object’s constructor will be called on the returned memory after the operator new exits.
A new expression calls operator new specifying the size of the type, then calls the type’s constructor on that memory, and then returns a pointer to the object that was created.
Thus, an expression like new MyClass in your example is roughly equivalent (not exactly) to this:
//MyClass *cls = new MyClass;
void *mem = :: operator new (sizeof(MyClass));
MyClass *cls = static_cast<MyClass*>(mem);
cls->MyClass();
And the converse is true for the delete expression, which calls the type’s destructor, and then calls operator delete to deallocate the raw memory, eg:
//delete cls;
cls->~MyClass();
:: operator delete (cls);
It seems you're looking for a Factory function. A factory is a dedicated function (or even a class) that produced instances of a class.
E.g.
#include <memory>
struct MyClass { int members[8]; };
std::unique_ptr<MyClass> MyClassFactory() {
auto inst = std::make_unique<MyClass>();
// assign some stuff to members
return inst;
}
Suppose I have defined a class called Entity which has a data member which is a pointer to int. So for example
class Entity {
public:
int* ptr;
// other stuff
};
Is there a way to give the type int* a constructor which takes an Entity object? If I have an Entity object called my_entity, I'd like to be able to do something like this
int* p(my_entity);
or this
int* p = my_entity;
which would require the compiler implicitly call a constructor for int* that takes an Entity.
Is this possible? (I know I could define a public get_pointer() method in the Entity class and do something like int* p = my_entity.get_pointer(); but this seems clunky.)
Well, there is no constructor for a basic pointer - in the sense that there is no function implicitly called in order to initialise the pointer.
The closest you can come is to use a user-defined conversion operator function
class Entity
{
public:
operator int *();
};
Entity::operator int *()
{
// return something appropriate that is of type int *
}
// sample usage in a function somewhere
int *p = some_entity; // implicitly conversion that calls the operator int *()
int *another_p = static_cast<int *>(some_entity); // explicit conversion
int *yet_another_p = some_entity.operator int *();
There are variants of this, depending on what form of const qualification is needed (e.g. if the operator function doesn't change the object it acts on, it should be const and may be defined as operator const int *()).
It is necessary to ensure that the pointer returned by the operator function is treated appropriately. If the user defined operator function returns a member of some_entity, it cannot be used once some_entity ceases to exist. Similarly, if it uses dynamic memory allocation (e.g. return the result of a new expression) the caller must explicitly release that memory to avoid a memory leak.
You cant make a constructor for primitive types. Also there is no need to do this using constructor, you could just use a getter as you already mentioned, or a function to which you pass an Entity and int and store the int to Entity.
Also you can use a user-defined conversion as #Some programmer dude said and do something like:
int *p = (int*)my_entity;
Suppose i have this sample code:
class A
{
public:
static void* operator new(size_t sz);
private:
int xA;
float yA;
};
class B : public A
{
private:
int xB;
float yB;
};
void* A::operator new(size_t sz)
{
void* ptr = (void*)new B();
return ptr;
}
int main()
{
B* b = (B*) new A();
// Use b ..
delete b;
return 0;
}
Here the constructors will be called in that order (tested in VS2012):
A constructor
B constructor
A constructor
The first two constructors calls are because of the new B() in the overloaded operator new function.
But then the A constuctor will be called again on the pointer returned by the function because the overloaded operator new is supposed to return a pointer to free memory (without creating the object), so the constructor is called again.
If i use the pointer b in this example, is this undefined behaviour?
The code you posted has endless recursion, since you call
A::operator new from within A::operator new; class B
inherits the operator new from A.
Beyond that, you lie to the compiler, which results in undefined
behavior. After new A, you have a pointer to an object whose
type is A. You can legally convert its address to a B*, but
all you can do with that B* is convert it back to an A*;
anything else is undefined behavior.
And it's not clear what you're trying to achieve with the new
B in A::operator new. The compiler will consider any memory
returned from an operator new as raw memory; in this case, it
will construct an A object in it, and from then on out, all
you have is an A object. Any attempt to use it as a B
object is undefined behavior. (And of course, if you actually
need to destruct the B created in A::operator new, you can't
because you've overwritten it.
Finally: you don't have to declare operator new as static;
it implicily is, and it's idiomatic not to write the static in
this case. Similarly, when assigning the results of new B to
a void*, the conversion is idiomatic, and it is idiomatic not
to make it explicit. (It's also best to avoid the C style
casts, since they hide too many errors.)
In general , operator new() should not CREATE an object, it should create space for an object. Your code will overwrite a B object with an A object, and then use it as a B object, and yes, that would be "undefined" (probably covered in the docs under "casting an object to a different type that it wasn't originally created as).
This may appear to work in this particular case, but if the constructor of B is more complex (e.g. there are virtual functions in B), it would immediately fail to work correctly.
If you want to allocate memory for an object, you could do:L
void* A::operator new(size_t sz)
{
void* ptr = (void*)::new unsigned char[sz];
return ptr;
}
Now you are not calling two different constructors for the same object!
The contract of operator new is just the memory allocation, the initialization is done later by the new-expression (by calling the constructor) or by program code if you call the operator directly.
What you are trying to do cannot be done, not like that. You could redesign to use a factory member function that would return a pointer to a B object, for example...
I am working with a class that is mostly working fine, but I am doing some functionality that I might be having a recursive function return a NULLpointer of the class type as a control, and so it might be assigning a NULL pointer to my class object so long story short:
Thing& Thing::operator=(Thing * _other){
if (_other == NULL){
*this = NULL; // compiler throws here
return *this;
}
// does other assignment work
return *this;
}
my compiler VS2010 throws that this is not an I-value. so how do I set the value to NULL, or is it even possible to set an item to NULL from inside?
EDIT: modified this to *this though for some reason now the program breaks with infinite calls to the assignment operator. no idea what is going on
You are trying to write a "nullable" class. Consider the "null" state to be one of the states an instance of Thing can be in, and don't convolute it with pointer semantics.
The general method would be to add a boolean flag to your class that keeps track of whether an instance is in null state or not. I would implement it like this:
class Thing
{
private:
bool m_null;
public:
void setnull() { m_null = true; }
bool isnull() const { return m_null; }
Thing() : m_null(true) {}
... // rest of class
};
And now the default assignment operator works fine.
You cannot directly set a value to the this pointer. Hence
this = NULL;
is semantically and syntactically wrong.
You can use exceptions to check if _other is NULL. For example:
class null_object_exception : public virtual exception {};
...
if (_other == NULL) throw null_object_exception();
To perform a NULL assignment:
Thing the_thing, other_thing;
try { the_thing = &other_thing; }
catch( const null_object_exception& e ) { the_thing = NULL; }
what are the member variables of Thing class?
if you want to show that the object is somehow without value or not intialized, you would better assign fileds 0 (for integers) and null(for pointers) etc, instead of assigning "this" which is constant.
Short answer, no, you can't assign to this in C++.
Longer answer; for your assignment operator to even be called, you'd have to have a construct like;
MyObject a;
a = NULL; // can change the content of `a` but not which object the name `a` refers to.
If you're thinking about this construct;
MyObject *a;
a = NULL;
your assignment operator won't even be called since it is an operator on the object, not the pointer. Assigning to the pointer a will work without you defining an assignment operator.
You CANNOT assign to this.
Also, you should take your arguments by const reference, so Thing& operator= (const Thing& other)
There's a great SO question in C++-faq tag about operator overloading, you can find it here
I've been searching for a solution to this problem but can't seem to find one. I'm sure this general question has been asked before somewhere but hopefully you can help with my specific situation...
I have a class template someClass that contain the following (private) members:
int size_x;
int size_y;
int size_total;
T * grid;
someClass contains a constructor that looks like this:
someClass (const int x, const int y)
: size_x (x), size_y (y), size_total (x*y)
{
grid = new T [size_total];
}
a copy constructor that looks like this:
someClass (const someClass & rhs)
{
size_x = rhs.size_x;
size_y = rhs.size_y;
size_total = rhs.size_total;
grid = new T [size_total];
memcpy(grid, rhs.grid, size_total*sizeof(T));
}
a member function that looks like this:
T * retGrid (void) const
{
return grid;
}
and an assignment operator that looks like this:
someClass & operator= (const someClass & rhs)
{
if (this != &rhs)
{
size_x = rhs.size_x;
size_y = rhs.size_y;
size_total = rhs.size_total;
grid = new T [size_total];
memcpy(grid, rhs.grid, size_total*sizeof(T));
}
return *this;
}
I'm trying to pass the following two someClass objects
someClass<double> *I1 = new someClass<double>(10,10);
someClass<double> I2 = *I1;
to a function outside of the someClass class with the following prototype:
int someFunction(double *arr);
This call works fine:
int status;
status = someFunction(I1->retGrid()); // Properly working function call
but this does not
status = someFunction(&I2.retGrid()); // Compiler gives error that says "error: invalid lvalue in unary &"
And if I call someFunction like this:
status = someFunction(I2.retGrid()); // Compiler gives no error but function returns error value in status
the code compiles but I get a run-time error (a bad status value from another function call within someFunction).
How can I properly pass I2 to someFunction?
Many thanks...
You are trying to take address of the temporary object (in this case, a pointer but this doesn't really matter) returned by retGrid. Hence you cannot use the & approach.
Without the ampersand, you would pass the internal array from I2 to someFunction. If that's not fine for you (i.e. since you get some kind of runtime error), consider making a copy of this array and passing it to someFunction instead.
When you have pointers in your class and you have to allocate memory for each object, you need to define a copy constructor and an assignment operator. You only added the later. This initialization
someClass<double> I2 = *I1;
is actually performed with a copy constructor, not with the assignment operator. It is identical to
someClass<double> I2(*I1);
However, it is wrong, because you only allocate memory for grid. But if grid was already allocated (from a previous assignment) you'd leak memory. So it should look like this:
someClass & operator= (const someClass & rhs)
{
if (this != &rhs)
{
size_x = rhs.size_x;
size_y = rhs.size_y;
size_total = rhs.size_total;
delete [] grid;
grid = new T [size_total];
memcpy(grid, rhs.grid, size_total*sizeof(T));
}
return *this;
}
First question: why aren't use using std::vector, instead of
trying to manage the memory yourself. You don't show the
destructor; I presume you free the memory there. But there are
still problems:
In the copy constructor, you use memcpy. That's not a problem
when you instantiate over double, but it could be a problem
for other types. You should be using std::copy.
If you were using std::vector, and retGrid still needed to
return a T*, it would be return &grid[0];.
The assignment operator is broken. It leaks any previous
memory, and if the new fails, it leaves the object in an
inconsistent state. (Having to check for self-assignment is
usually a hint that something is wrong.) A correct assignment
operator will do all operations which might fail before changing
anything in the object. You might search for information about
the swap idiom, but something like the following would also
work:
.
SomeClass&
SomeClass<T>::operator=( SomeClass const& other )
{
T* newGrid = new T[other.size_total];
std::copy( other.grid, other.grid + other.size_total, newGrid );
delete [] grid;
size_x = other.size_x;
size_y = other.size_y;
size_total = other.size_total;
grid = newGrid;
return *this;
}
You might want to optimize this if the size_total are equal
(or size_total <= other.size_total).
And of course, if you use std::vector, the compiler generated
assignment operator and copy constructor are sufficient; you
don't have to write anything.
Is there any reason why you use a pointer for I1? (Or is
this just an artifact of a larger context from which you
extracted the code?)
Concerning someFunction( &I2.retGrid() );,
someClass::retGrid() returns a pointer. Regardless of whether
you call the function through a pointer or an object. Taking
the address results in a T**.
Concerning the last call, there is nothing that would cause
a problem here in the code you've shown us. As long as I2 is
in scope and hasn't deleted it's object, there should be no
problem. This is the correct way of calling the function on an
object. The problem in your code is elsewhere.
I'm not sure of the runtime error that you are getting but status = someFunction(&I2.retGrid()); is passing pointer to a temporary object.
The runtime error could be because of missing copy constructor that is invoked in someClass<double> I2 = *I1;
Thank you to everyone for the extremely useful comments, especially those by AAT, David Rodriguez - dribeas, James Kanze, and Marius Bancila.
It turns out the problem was improper interface with a third-party function inside someFunction. I found and fixed the error after some sleep and now the call:
status = someFunction(I2.retGrid()); // Compiler gives no error but function returns error value in status
works correctly.
But this discussion brought other very important related issues to light, namely the memory management issues related to my copy constructor and assignment operator and suggested use of vectors. I believe this thread has a lot of value on those merits.