Home > Archive > VC Language > January 2006 > Re: Overloading new
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Re: Overloading new
|
|
| Victor Bazarov 2006-01-24, 7:07 pm |
| maynard wrote:
> I'm attempting to overload the new[] operator. This is my first
> attempt at doing so, but I've found quite a few articles to help me
> out. Here is the source for my overloaded operator new[]:
>
> class myClass
> {
> public:
> myClass();
> ~myClass();
> void *operator new[](size_t, long);
> protected:
> double *v1;
> double *v2;
> long num_pts;
> };
>
> myClass::myClass()
> { //ctor... }
>
> myClass::~myClass()
> { //dtor... }
>
> void *myClass::operator new[](size_t sz, long numpts)
> {
Have you seen what 'sz' is before you scale it down?
> sz /= sizeof(myClass);
I am not sure why but you actually lose a chunk of your array here.
> myClass *x = ::new myClass[sz];
I don't think you're supposed to do that here. You're supposed to
allocate a char array of size 'sz' (without dividing it) and then just
return it.
>
> for(size_t j = 0; j < sz; j++){
> x[j].v1 = new double[numpts];
> x[j].v2 = new double[numpts];
> for (long i=0;i<numpts;++i){
> x[j].v1[i] = 0.;
> x[j].v2[i] = 0.;
> }
> x[j].num_pts = numpts;
> }
> return x;
> }
>
> I pass the "message" as follows:
>
> int numObjs = 100;
> long totalPts = 100000;
> myClass* myObj = new(totalPts) myClass[numObjs];
>
> When I step through this in the debugger (MS VC++ .NET), it appears
> that the local "x" (in operator new[]) is properly allocated and
> initialized. However, when it returns, myObj isn't. I also noticed in
> the debugger that the memory location for "x" is 0x00321714, but myObj
> (after new[] returns) is 0x00321718.
>
> With that said, two questions...have I properly defined & implemented
> my new[] operator? Is there a problem in the debugger??
I don't think you properly implemented it. Check out the following page
http://www.codeguru.com/cpp/tic/tic0139.shtml
The system calls "new operator" that figures out the size (your 'sz') and
then calls "operator new[]", after which it takes the returned pointer and
apparently adjusts it. You're not supposed to fiddle with the array
before "new operator" gives it back to your 'myObj'.
I understand *why* you wanted to do what you did. You just tried doing it
at the wrong time...
V
| |
| Victor Bazarov 2006-01-24, 7:07 pm |
| maynard wrote:
> [..]
>
> If this is the case, then I'm going to have to try something else. In
> reality, although I didn't show it in my example, I'm deriving from
> another class (written by somebody else) that only allows
> initialization through overloaded constructors (bad, bad, bad!). Of
> course, this doesn't work if you try and declare an array of these
> objects. I may have to implement a simple allocation method
> instead...I was just trying to implement a "quick fix" and something
> clean to use, that's all.
>
> As usual, thanks for your help V!
You're most welcome!
Take a look how 'std::vector' does that. It uses "placement new" to
create and copy all those elements when it needs to reallocate. You need
to do the same thing, most likely:
#include <memory>
class SomeOtherClass {
int i;
public:
SomeOtherClass(int i) : i(i) {}
int get() const { return i; }
};
class MyClass : public SomeOtherClass {
public:
MyClass(int i) : SomeOtherClass(i) {}
};
MyClass* arrayCreator(size_t howmany, int argument) {
char *storage = new char[howmany * sizeof(MyClass)];
for (int i = 0; i < howmany; ++i)
new (storage + sizeof(MyClass) * i) MyClass(argument);
return reinterpret_cast<MyClass*>(storage);
}
void arrayDisposer(MyClass* arr)
{
delete[] reinterpret_cast<char*>(arr);
}
int main() {
MyClass *myArray(arrayCreator(100, 42));
int a = myArray[77].get();
arrayDisposer(myArray);
}
V
| |
| Igor Tandetnik 2006-01-24, 7:07 pm |
| Victor Bazarov <v.Abazarov@comAcast.net> wrote:
> MyClass* arrayCreator(size_t howmany, int argument) {
> char *storage = new char[howmany * sizeof(MyClass)];
> for (int i = 0; i < howmany; ++i)
> new (storage + sizeof(MyClass) * i) MyClass(argument);
> return reinterpret_cast<MyClass*>(storage);
> }
>
> void arrayDisposer(MyClass* arr)
> {
> delete[] reinterpret_cast<char*>(arr);
> }
It would be prudent to run destructors before freeing the memory. And
for that, you would need to keep track of the number of elements
allocated.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
| |
| Victor Bazarov 2006-01-24, 7:07 pm |
| Igor Tandetnik wrote:
> Victor Bazarov <v.Abazarov@comAcast.net> wrote:
>
>
>
> It would be prudent to run destructors before freeing the memory. And
> for that, you would need to keep track of the number of elements
> allocated.
Absolutely. My erroneous omission.
V
| |
| Victor Bazarov 2006-01-24, 7:07 pm |
| maynard wrote:
> Victor Bazarov wrote:
>
Should be:
void arrayDisposer(MyClass* arr, size_t howmany)
[color=darkred]
Add:
while (howmany)
arr[--howmany].~MyClass();
[color=darkred]
Change to:
arrayDisposer(myArray, 100);
[color=darkred]
>
>
> That looks to be exactly what I need to do. I'll give it a try.
>
See corrections above, and thank Igor again for catching it!
V
--
Please remove capital As from my address when replying by mail
Sorry, I do not respond to top-posted replies, please don't ask
| |
| Victor Bazarov 2006-01-24, 7:07 pm |
| maynard wrote:
> Victor Bazarov wrote:
>
>
>
> Victor, of course, it's never as easy as it seems. I've overlooked
> something...MyClass has dynamically allocated members (dynamic arrays
> of doubles). The MyClass constructor used above is intended to
> allocate all of these arrays with *size* "argument", not simply to
> initialize some value to "argument". I see how this will corrupt the
> memory allocated using the above bit of code, but I can't quite figure
> out how to resolve this. I think my main problem is that I do not know
> the size (sequentially) of an object of MyClass until it is
> instantiated. Therefore, the above approach wouldn't quite work (since
> one would need to know how much to increment the "new placement" for
> each allocated object of MyClass, right?).
>
> Am I making any sense?
Well... Don't make me say "no".
If you read about "placement new", you'll know that it actually constructs
the object. Now, the size of the object does not depend on what other
dynamic memory it might allocate. That allocation happens _outside_ of
the object's own "instance" memory.
So, trust me or spend some time figuring it out (which I recommend), but
the code above should work fine whatever the constructor for 'MyClass'
does with the argument.
V
| |
| Igor Tandetnik 2006-01-24, 7:07 pm |
| maynard <pfrye@spsu.edu> wrote:
> Victor Bazarov wrote:
>
> Victor, of course, it's never as easy as it seems. I've overlooked
> something...MyClass has dynamically allocated members (dynamic arrays
> of doubles). The MyClass constructor used above is intended to
> allocate all of these arrays with *size* "argument", not simply to
> initialize some value to "argument".
Your constructor can do whatever it wants, including allocating memory.
What seems to be the problem?
> I see how this will corrupt the
> memory allocated using the above bit of code
What makes you think so?
> but I can't quite figure
> out how to resolve this. I think my main problem is that I do not
> know the size (sequentially) of an object of MyClass
Of course you do - it's sizeof(MyClass). The fact that it contains
members that are pointers to dynamically allocated arrays is irrelevant.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
| |
| Victor Bazarov 2006-01-25, 7:23 pm |
| maynard wrote:
> Victor Bazarov wrote:
>
>
>
> Not that it really matters, but I thought I'd let you guys know I got
> it figured out. It took me a while, but for good reason. In my
> implementation, the MyClass class is a class that was written by
> somebody else. I (as a bad user) assumed this class had been fully
> tested...I was, of course, wrong. The constructor MyClass(argument)
> incorrectly attempts to initialize "this" by explicitly calling another
You ought to put [explicitly calling] in double quotes as well because
it is impossible to _call_ a constructor _explicitly_. The syntax below
simply creates a temporary object of type 'MyClass', and the temporary
disappears as soon as the semicolon is reached.
I am sure you knew that, I'm just commenting for the benefit of others.
> constructor (MyClass(arg1, arg2)), like this:
>
> class MyClass
> {
> MyClass();
> MyClass(int);
> MyClass(int, int);
> };
>
> MyClass::MyClass()
> {...}
>
> MyClass::MyClass(int i)
> {
> MyClass::MyClass(0, i);
> }
>
> MyClass::MyClass(int j, int i)
> {...}
>
V
| |
| Alexander Grigoriev 2006-01-25, 7:23 pm |
|
"Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
news:%23usmhFcIGHA.2036@TK2MSFTNGP14.phx.gbl...[color=darkred]
>
> You ought to put [explicitly calling] in double quotes as well because
> it is impossible to _call_ a constructor _explicitly_. The syntax below
> simply creates a temporary object of type 'MyClass', and the temporary
> disappears as soon as the semicolon is reached.
>
> I am sure you knew that, I'm just commenting for the benefit of others.
>
I'm not sure if it's supposed to compile at all. I would expect the
following to compile and produce a temporary:
MyClass::MyClass(int i)
{
MyClass(0, i);
}
Note no fully qualified name in the invocation.
| |
| Victor Bazarov 2006-01-25, 7:23 pm |
| Alexander Grigoriev wrote:
> "Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
> news:%23usmhFcIGHA.2036@TK2MSFTNGP14.phx.gbl...
>
>
>
> I'm not sure if it's supposed to compile at all. I would expect the
> following to compile and produce a temporary:
>
> MyClass::MyClass(int i)
> {
> MyClass(0, i);
> }
>
> Note no fully qualified name in the invocation.
It should compile.
The name of a class is the member of that class. So, you can write
MyClass::MyClass::MyClass::MyClass::MyCl
ass::MyClass::MyClass(0, i);
it will mean the same thing, the class itself.
V
| |
| Ben Voigt 2006-01-26, 7:08 pm |
|
"Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
news:OVh5t2cIGHA.2300@TK2MSFTNGP15.phx.gbl...
> Alexander Grigoriev wrote:
>
> It should compile.
>
> The name of a class is the member of that class. So, you can write
>
> MyClass::MyClass::MyClass::MyClass::MyCl
ass::MyClass::MyClass(0, i);
?????
I thought it *didn't* find MyClass::MyClass in the current class, so looked
at global (or namespace or etc.) scope and found it.
>
> it will mean the same thing, the class itself.
>
> V
| |
| Victor Bazarov 2006-01-26, 7:08 pm |
| Ben Voigt wrote:
> "Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
> news:OVh5t2cIGHA.2300@TK2MSFTNGP15.phx.gbl...
>
>
>
> ?????
How to interpret your question marks here?
> I thought it *didn't* find MyClass::MyClass in the current class, so looked
> at global (or namespace or etc.) scope and found it.
I don't understand this statement either.
I was replying that having 'MyClass::MyClass' anywhere in a member
function should be just like having 'MyClass'. Since 'MyClass' name is
a member of 'MyClass' class, no namespace lookup is ever done, as far as
I can conclude. Do you have any evidence to the contrary?
V
|
|
|
|
|