为什么没有分配原始数据类型的内存?
这个问题在这里已经有了答案:
当我们创建一个NSString *
变量时,我们也不会为此分配内存。
当调用alloc
时,我们只分配内存,或者直接由我们或者在我们调用的方法中。
一个NSString
对象存在于我们分配的内存堆中,但NSString *
变量(即,指向NSString
对象的指针)存在于我们不分配的堆栈中的内存中。
例如,给定这两个变量:
NSString *stringOne;
NSString *stringTwo;
到目前为止,在堆中没有分配任何内存,尽管它们确实存在于内存中,就像存储器中存在char
, BOOL
或int
。
NSString *stringOne = [[NSString alloc] initWithString:@"Hello world"];
NSString *stringTwo = stringOne;
现在发生了什么? 我们在堆上为NSString
对象分配了一些内存。 然后我们初始化这个内存来表示字符串“Hello world”,然后返回一个指向这个对象的指针并将它分配给stringOne
。
接下来,我们简单地将该指针复制到我们用于stringTwo
的堆栈内存中。 我们没有在堆上分配任何额外的内存。 我们只是将两个字符串变量指向堆中相同的已分配内存。
在评论中链接的问题和答案有更多的堆栈和堆内存的解释,这将解答你的一些问题。
值得注意的是,很多其他编程语言(如C ++)允许在堆栈上创建对象,在这种情况下,我们不会像堆对象那样分配它们。 它们确实存在于内存中,与原始数据类型更类似。
存在过分简单化的风险,数据有三类内存:1)静态,2)堆栈3)堆。
它们以不同的方式分配。
如果你有
static char something ;
在一个函数中定义或
char something ;
在函数之外,数据由链接器使用来自编译器的指令并由程序加载器分配来定义。
几乎每个存在的处理器都使用堆栈来支持嵌套数据(例如函数调用)。 堆栈是每个进程(和每个处理器模式)都存在的一块内存。 有一个称为堆栈指针的硬件寄存器,用于标识堆栈的当前位置。 通常SP从堆栈的高端开始向下工作。 要在堆栈中分配内存,程序会从堆栈指针中减去所需的字节数。 为了释放,它添加到堆栈指针。 分配和释放总是在同一端进行。
然后在堆栈上有两个操作。 PUSH意味着把东西放在堆栈上。 POP删除它。 大多数处理器都有指示PUSH和POP
如果你有
char something
在一个函数中定义的内存是由程序按照编译器的指示通过执行类似这样的操作来调整堆栈指针(我暂时忽略了一个帧指针)
SUB BYTESNEEDED, SP
在进入功能并通过干扰释放后
ADD BYTESNEEDED, SP
在离开功能之前。 在函数执行过程中,局部变量位于堆栈指针的偏移处。
这通常通过使用第二个寄存器完成,通常称为帧指针。 一个函数在开始时通常会做这样的事情
PUSH FP ; Save the old Frame Point
MOV SP FP ; Save the stack pointer
SUB BYTESNEEDED, SP
最后,函数做了类似的事情
MOV FP,SP; 释放由函数POP FP分配的所有堆栈; 恢复旧的堆栈指针
使用两个寄存器的原因是可以从堆栈动态分配数据。
这是一个常见的函数(虽然我相信它不是一个标准的C函数),称为alloca,它是从堆栈分配的malloc的替代方案
void dosomething (int amount)
{
char *data = alloca (amount) ;
}
使用alloca时,当函数返回并重置堆栈时,数据将自动释放。
对于你的问题,这是一个漫长的回答。 是的,当声明一个字符时,必须有一个分配。 但是,这种分配是在幕后完成的,没有您的努力。
链接地址: http://www.djcxy.com/p/2265.html