为什么没有分配原始数据类型的内存?

tri*_*Ant 1 memory cocoa memory-management objective-c primitive-types

原始数据类型(如char,bool和int)具有一些内存.假设char,它有1个字节的内存.当我们在代码中使用char变量时,变量必须要求1个字节的内存.在这种情况下,我们为什么不分配内存.因为我们从不为它分配内存,它如何使用内存,即在这种情况下CPU是否为它分配内存.我也读过某些地方,原始数据类型被放在堆栈上并在完成工作时被移除.什么样的堆栈?在这种情况下,堆栈是如何形成的?

nhg*_*rif 5

当我们创建NSString *变量时,我们也不为此分配内存.

我们只在alloc被调用时直接由我们或在我们调用的方法内部分配内存.

一个NSString对象存在于我们已分配的内存堆中,但是NSString *变量(即指向NSString对象的指针)存在于堆栈的内存中,我们没有分配.

例如,给定以下两个变量:

NSString *stringOne;
NSString *stringTwo;
Run Code Online (Sandbox Code Playgroud)

到目前为止,无论是已经在堆中分配任何内存,他们虽然存在于内存中的完全相同的方式char,BOOLint存在于内存中.

NSString *stringOne = [[NSString alloc] initWithString:@"Hello world"];
NSString *stringTwo = stringOne;
Run Code Online (Sandbox Code Playgroud)

现在发生了什么?我们在堆上为一个NSString对象分配了一些内存.然后,我们初始化此内存以表示字符串"Hello world",然后返回指向此对象的指针并将其分配给stringOne.

接下来,我们只是将指针复制到我们正在使用的堆栈内存中stringTwo.我们没有在堆上分配任何额外的内存.我们简单地将两个字符串变量指向堆上相同的已分配内存.

注释中链接问题和答案jsd对堆栈和堆内存有更多的解释,这将解答您的一些问题.

还值得注意的是,许多其他编程语言(如C++)允许在堆栈上创建对象,在这种情况下,我们不会像堆对象那样分配它们.它们确实存在于内存中,与原始数据类型更相似.

  • 对......相关利益的一个实施细节(但绝不会使答案无效); `[[NSString alloc] initWithString:@"Hello world"]`实际上不会在堆上创建一个字符串.它将返回编译器在mach-o文件中放置的__NSCFConstantString(或其所谓的任何内容).这只是一个有趣的细节,因为它不会改变你对所述字符串消费的任何改变; 它应该像任何其他对象一样对待. (4认同)

use*_*003 5

过于简单化的风险,数据有三类内存:1)静态,2)堆栈3)堆.

它们以不同的方式分配.

如果你有

 static char something ;
Run Code Online (Sandbox Code Playgroud)

在函数中定义或

char something ;
Run Code Online (Sandbox Code Playgroud)

在函数之外,该数据由链接器使用编译器的指令定义并由程序加载器分配.

几乎每个处理器都使用堆栈来支持嵌套数据(例如,函数调用).堆栈是一个存储器块,存在于每个进程(以及每个处理器模式).有一个称为堆栈指针的硬件寄存器,用于标识堆栈的当前位置.通常SP从堆栈的高端开始并向下工作.要在堆栈上分配内存,程序会从堆栈指针中减去所需的字节数.要解除分配,它会添加到堆栈指针.分配和解除分配始终在同一端进行.

然后堆栈上有两个操作.PUSH意味着把东西放在堆栈上.POP删除它.大多数处理器都有PUSH和POP的指令

如果你有

 char something
Run Code Online (Sandbox Code Playgroud)

在函数中定义的内存由程序按照编译器的指示通过执行类似的操作来调整堆栈指针(我现在省略了一个帧指针)

 SUB   BYTESNEEDED, SP
Run Code Online (Sandbox Code Playgroud)

在进入功能并通过执行释放

ADD BYTESNEEDED, SP
Run Code Online (Sandbox Code Playgroud)

在离开功能之前.在执行函数期间,局部变量处于堆栈指针的偏移量.

这通常通过使用第二个寄存器来完成,通常称为帧指针.一个函数通常在开始时做这样的事情

PUSH  FP       ; Save the old Frame Point 
MOV   SP  FP   ; Save the stack pointer
SUB   BYTESNEEDED, SP
Run Code Online (Sandbox Code Playgroud)

最后,函数做了类似的事情

MOV FP,SP; 释放POP FP功能分配的所有堆栈; 恢复旧的堆栈指针

使用两个寄存器的原因是可以从堆栈动态分配数据.

这是一个常见的函数(虽然我认为它不是标准的C函数),称为alloca,它是从堆栈分配的malloc的替代品

void dosomething (int amount)
{
    char *data = alloca (amount) ;
} 
Run Code Online (Sandbox Code Playgroud)

使用alloca,当函数返回并重置堆栈时,数据会自动释放.

对你的问题,这是一个冗长的回答.是的,当声明一个char时,必须有一个分配.但是,这种分配是在幕后完成的,您无需付出任何努力.