Re: NSCopyObject
Re: NSCopyObject
- Subject: Re: NSCopyObject
- From: Thomas Lachand-Robert <email@hidden>
- Date: Thu, 25 Apr 2002 23:44:43 +0200
Le jeudi 25 avril 2002, ` 08:56 , Robert Lee Dotson a icrit :
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
The matrices are meant to be created once, and never resized. What I want
is to send [myMatrix copy], and have two matrices, each with their own
copies of the data in *values. If I've got the terminology correct, what
I want is a deep copy.
I'm just unsure how NSAllocateObject works. I assume it parses the list
of instance variables, and creates enough memory in the object for each
int, float, pointer, etc. Then, if you pass it the extrabytes variable,
it will append that much extra free space to the object's allocation. But
how do I actually access that extra data buffer to write my float array?
Do I just make sure that my *float[] is last in the list of instance
variables, and as the array grows, it will fill this space? What if I
have multiple arrays?
No. NSAllocateObject basically just call calloc with a computed size as
follows (note that's only a rough guess, I don't know the actual code):
void* NSAllocateObject(Class c, unsigned additionalsize, void* zone) {
void *p;
unsigned size =
sizeof( instances of c ) // provided by the ObjC runtime, from
compiler's information
+ additionalsize; // the required supplementary room
p = calloc(size); // actually does use zone, so it's not calloc but
NSAllocateMemoryPages
p->isa = c; // the 'isa' pointer gives the class of an ObjC object
return p;
}
So it's really simple. With your declaration of LCVMatrix below, every
object uses 16 bytes:
sizeof(isa) // exists in any ObjC object, is a pointer
+ sizeof(int) *2 // for rows and colums
+ sizeof( float*) // for values.
So you don't have any room for your values, you need to allocate more. If
you intend to allocate it in the very same object, you don't need the
float*, hence my previous declaration:
@interface LCVMatrix : NSObject {
int rows,
columns;
float values[0];
}
Note the array uses 0 bytes! But if you allocate more, like that:
+(id) allocWithZone:(NSZone*)zone {
// assume that rows and columns are the same for every matrix
return NSAllocateObject(self, sizeof(float) * (rows * columns), zone);
}
you are sure to have the room for rows * columns in the array, so you can
use values[k] for k < rows * columns. (The additional room is always at
the end of the struct.)
Note that this doesn't work if you intend to do that:
int n = /*some computed value */, p = /*some other*/;
LCVMatrix *myMatrix = [[LCVMatrix alloc] initWithRows:n columns:p];
because alloc cannot know the intended size. Also you will not be able to
subclass LCVMatrix in the usual way, since additional fields would be
added in the values array. OTOH you can use directly NSCopyObject to copy
this object, since everything is here in the struct. Also you don't have
to do something in dealloc.
If you want to be able to choose the size while initializing, it's
probably easier to use your declaration below and do
values = malloc(sizeof(float) * (rows * columns))
in the init method (where rows and columns are known). In that case, there
is no need to override allocWithZone.
But to copy, it is a bit more complicated (and slower):
-(id) copyWithZone:(NSZone*)zone {
id m = NSCopyObject(self, 0, zone); // basically copies everything
// in particular m->values is now equal to values, which is wrong, so:
m->values = malloc(sizeof(float) * (rows * columns));
memcpy(m->values, values, (sizeof(float) * (rows * columns)));
return m;
}
and you need to free values in dealloc.
Due to the relaxed C syntax on arrays, you can still access elements with
values[k].
(It is possible to adapt the first way of doing for this case, but the
benefit in your case seems very small; let me know if you are still
interested.)
Le jeudi 25 avril 2002, ` 06:08 , Robert Lee Dotson a icrit :
Here's a quick version of my class:
@interface LCVMatrix : NSObject {
int rows,
columns;
float *values;
}
and allocation is
NSAllocateObject([LCVmatrix class], (sizeof(float) * (rows * columns)),
NULL).
Beware that you need to do that in the +alloc class method.
Then you have enough room in the values[] array to store the floats.
If you store the values in a separated array, as your declaration of a
pointer seems to indicate, you don't need to use NSAllocateObject. But
your values should be allocated by malloc (certainly not realloc!,
except if you resize your array).
Both ways have pros and cons. If you intend to resize the array, you
must use the second one.
Thomas Lachand-Robert
********************** email@hidden
<< Et le chemin est long du projet ` la chose. >> Molihre, Tartuffe.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.