NSString有哪些创建对象的方法?创建的对象分别存储在什么区域?

NSString有哪些创建对象的方法?创建的对象分别存储在什么区域?

一般通过NSString创建对象的方法有:

  1. NSString *string1 = @"123";
  2. NSString *string2 = [[NSString alloc] initWithString:@"123"];
  3. NSString *string3 = [NSString stringWithFormat:@"123"];
  4. NSString *string4 = [[NSString alloc] initWithFormat:@"123"];

这里面涉及到几个问题:
创建的对象存储在什么区?常量区?堆区?还是小对象?

因此,我们做打印,看结果分析:

//目的:看看字符串长度短的情况下
NSString *string0 = @"sun";//常量区
//目的:看看字符串长度很长的情况下
NSString *string1 = @"sundaopjd2221";//常量区
        
NSString *string2 = [[NSString alloc] init];//常量区
NSString *string3 = [[NSString alloc] initWithString:@"sun"];//常量区
//目的:看看字符串长度短的情况下,下一个存储空间地址是啥
NSString *string4 = [[NSString alloc] initWithString:@"sun2"];//常量区
//目的:看看字符串长度很长的情况下,有没有变化
NSString *string5 = [[NSString alloc] initWithString:@"sundaopjd2221"];//常量区
        
//目的:看看字符串长度短的情况下,存储空间地址
NSString *string6 = [NSString stringWithFormat:@"1"];//小对象
//目的:看看字符串长度短的情况下,下一个存储空间地址是啥
NSString *string7 = [NSString stringWithFormat:@"2"];//小对象
//目的:看看字符串长度很长的情况下,有没有变化
NSString *string8 = [NSString stringWithFormat:@"sundaopjd2221"];//存储在堆
//目的:观察堆空间的变化
NSString *string9 = [NSString stringWithFormat:@"sundaopjd222122"];//存储在堆

//目的:看看字符串长度短的情况下,存储空间地址
NSString *string10 = [[NSString alloc] initWithFormat:@"1"];//小对象
//目的:看看字符串长度短的情况下,下一个存储空间地址是啥
NSString *string11 = [[NSString alloc] initWithFormat:@"3"];//小对象
//目的:看看字符串长度很长的情况下,有没有变化
NSString *string12 = [[NSString alloc] initWithFormat:@"sundaopjd2221"];//存储在堆
//目的:观察堆空间的变化
NSString *string13 = [[NSString alloc] initWithFormat:@"sundaopjd2221222"];//存储在堆

//这个是指针本身的存储地址(栈)
NSLog(@"%p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p", &string0, &string1, &string2, &string3, &string4, &string5, &string6, &string7, &string8, &string9, &string10, &string11, &string12, &string13);
        
//看看string的类型
NSLog(@"%@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@", [string0 class], [string1 class], [string2 class], [string3 class], [string4 class], [string5 class], [string6 class], [string7 class], [string8 class], [string9 class], [string10 class], [string11 class], [string12 class], [string13 class]);

//这个是对象存储的地址
NSLog(@"%p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p", string0, string1, string2, string3, string4, string5, string6, string7, string8, string9, string10, string11, string12, string13);
        
//看看引用计数器个数
NSLog(@"%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", [string0 retainCount], [string1 retainCount], [string2 retainCount], [string3 retainCount], [string4 retainCount], [string5 retainCount], [string6 retainCount], [string7 retainCount], [string8 retainCount], [string9 retainCount], [string10 retainCount], [string11 retainCount], [string12 retainCount], [string13 retainCount]);

打印结果:
0x7ff7bfeff290, 0x7ff7bfeff288, 0x7ff7bfeff280, 0x7ff7bfeff278, 0x7ff7bfeff270, 0x7ff7bfeff268, 0x7ff7bfeff260, 0x7ff7bfeff258, 0x7ff7bfeff250, 0x7ff7bfeff248, 0x7ff7bfeff240, 0x7ff7bfeff238, 0x7ff7bfeff230, 0x7ff7bfeff228

__NSCFConstantString, __NSCFConstantString, __NSCFConstantString, __NSCFConstantString, __NSCFConstantString, __NSCFConstantString, NSTaggedPointerString, NSTaggedPointerString, __NSCFString, __NSCFString, NSTaggedPointerString, NSTaggedPointerString, __NSCFString, __NSCFString

//混淆关闭前
//0x100004038, 0x100004058, 0x7ff846c7c2d0, 0x100004038, 0x100004078, 0x100004058, 0x9329a7a56318529b, 0x9329a7a56318519b, 0x600000207100, 0x600000c04ba0, 0x9329a7a56318529b, 0x9329a7a56318509b, 0x600000207120, 0x600000c04bd0
//混淆关闭后
0x100004038, 0x100004058, 0x7ff846c7c2d0, 0x100004038, 0x100004078, 0x100004058, 0x3115, 0x3215, 0x600000209340, 0x600000c0cba0, 0x3115, 0x3215, 0x3315, 0x600000c0cbd0

-1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1

分析:

通过打印[string class]获取的类型:__NSCFConstantString,NSTaggedPointerString,__NSCFString
可以知道创建的对象分别存储在什么区:常量区、小对象、堆区

通过打印[string retainCount]获取引用计数器:-1,1的结果,可以区分:
-1:常量区或小对象
1:堆区

问:为啥retainCount会为-1?

这是因为retainCount是一个无符号整型typedef unsigned long NSUInteger;
因此,-1并不代表是真正的引用计数器的值

在iOS中,遇到retainCount返回-1(或者在某些情况下是UINT_MAX,因为retainCount返回的是NSUInteger,一个无符号整型)通常是指对象被标记为不可释放或具有“无限”的引用计数。这种情况通常发生在几种特殊对象上,这些对象由于各种原因,被系统视为“永久存活”的,直到应用程序结束。这样的对象不参与常规的引用计数管理,也就是说,无论对它们进行多少次retainrelease操作,它们都不会被销毁。

这里的-1或UINT_MAX并不表示实际的引用计数值,而是一个标志,表明这个对象是由系统以特殊方式管理的。对于开发者来说,这意味着这类对象的内存管理并不需要(也不应该)手动干预。

几个典型的例子包括:

  • 单例对象:如[UIApplication sharedApplication][NSFileManager defaultManager],这些单例在应用程序的整个生命周期内都应该保持活跃状态。
  • 字符串字面量:如NSString *str = @"constant string";,这些字符串在编译时被创建,并存储在应用程序的二进制文件中。它们在整个应用程序的生命周期内都是有效的,因此被认为是具有“无限”引用计数的。
  • 标准框架对象:某些由系统框架创建并管理的对象,可能也会被标记为具有“无限”引用计数。

结论:

  • 通过NSString *str = @"1"[NSString alloc] initWithString:@"1"]创建的对象一致,都是存储在常量区

虽然有initWithString,有init,但也是放在常量区,不增加引用计数器

  • 通过[NSString stringWithFormat:@"2"];[[NSString alloc] initWithFormat:@"2"];创建的对象一致,当字符串长度小的时候(小于10)都是小对象,字符串长度过长的时候(大于等于10)存储在堆区域
//9个数
NSString *string11 = [[NSString alloc] initWithFormat:@"123456789"];
//10个数
NSString *string12 = [[NSString alloc] initWithFormat:@"1234567890"];
打印类型结果:
NSTaggedPointerString, __NSCFString
  • 小对象的引用,与小对象本身的地址不一致,即NSString *string6 = [NSString stringWithFormat:@"1"]; string6的地址,与[NSString stringWithFormat:@"1"];的地址不一致。
    因为string6是在栈上的,然后string6内部有一部分特定区域,存放小对象"1"

猜测:小对象存储在栈区

在这里插入图片描述

在这里插入图片描述

在现在的版本中,为了保证数据安全,苹果对 Tagged Pointer 做了数据混淆,开发者通过打印指针无法判断它是不是一个Tagged Pointer,更无法读取Tagged Pointer的存储数据。
所以在分析Tagged Pointer之前,我们需要先关闭Tagged Pointer的数据混淆,以方便我们调试程序。通过设置环境变量OBJC_DISABLE_TAG_OBFUSCATION为YES。

iOS - 老生常谈内存管理(五):Tagged Pointer

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/495511.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java设计模式—备忘录模式(快照模式)

定义 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,很多软件都提供了撤销(Undo)操作&#…

白酒:浓香型白酒的典型代表与特点

云仓酒庄的豪迈白酒作为白酒的品牌,具有一系列与众不同的特点和优势。下面云仓酒庄的豪迈白酒将从典型性、品质、口感和包装等方面深入分析白酒的特点,以及它如何体现浓香型白酒的魅力。 浓香型白酒是中国白酒的重要分支,以浓郁的香味和与众不…

设计模式之原型模式讲解

原型模式本身就是一种很简单的模式,在Java当中,由于内置了Cloneable 接口,就使得原型模式在Java中的实现变得非常简单。UML图如下: 我们来举一个生成新员工的例子来帮助大家理解。 import java.util.Date; public class Employee…

SI案例分享--冷却液对PCIe链路性能的影响

目录 0 引言 1 PCIe线缆组件在不同冷却方式中的性能对比 1.1 配置Paddle card互连的电缆组件测试结果(cable-1) 1.2 直接焊接互连的电缆组件测试结果(cable-2) 1.3 一侧配置Paddle card、一侧直接焊接互连的电缆组件测试结果…

阿里云账号怎么注册?看这一篇就够了

阿里云账号怎么注册?阿里云账号支持手机号注册、阿里云APP注册、淘宝、支付宝和钉钉多种注册方式,账号注册后需要通过实名认证才可以购买或使用云产品,使用淘宝、支付宝或钉钉注册方式可以免去实名认证步骤,阿里云百科aliyunbaike…

深入解析MD5哈希算法:原理、应用与安全性

码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 ! 本文将深入探讨MD5哈希算法的工作原理、应用场景以及安全性问题。我们将了解MD5如何生成固定长度的哈希值,以及它在数…

Leo赠书活动-21期 《一篇讲明白 Hadoop 生态的三大部件》

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 赠书活动专栏 ✨特色专栏:…

【OpenAI援引马斯克评价中国】小米汽车 SU7 顶配版或超 30 万/OpenAI 加持机器人亮相/荣耀已投入 100 亿研发 AI

雷军:共建一个更良性包容的汽车市场舆论环境 Figure 与 OpenAI 联手推出新机器人 亚马逊和 Google 悄悄降低对生成式 AI 的预期 小米生态链模式大改革,将进行分级管理 掌阅科技:致力打造国内首款真正 AI 阅读应用 荣耀称已投入 100 亿用于 AI…

Ipython与Jupyter之间的关系

IPython 和 Jupyter 之间的关系可以从它们的历史和目标中得到很好的解释。IPython(Interactive Python)最初是由 Fernando Prez 于 2001 年创建的,旨在提升 Python 的交互式计算体验。它提供了一个强大的交互式 Python shell 和一个面向高效计…

C语言例4-27:计算1+2+...+100之和(利用while语句实现)。

代码如下&#xff1a; //计算12...100之和&#xff08;利用while语句实现&#xff09;。 #include<stdio.h> int main(void) {int n1, sum0;while(n<100){ //复合语句作为当型循环结构的循环体sumsumn;n;}printf("sum %d\n",sum);retu…

Phoenix伪分布安装

引言 Phoenix是构建在HBase上的一个SQL层&#xff0c;能让我们用标准的JDBC APIs而不是HBase客户端APIs来创建表&#xff0c;插入数据和对HBase数据进行查询。Phoenix完全使用Java编写&#xff0c;作为HBase内嵌的JDBC驱动。Phoenix查询引擎会将SQL查询转换为一个或多个HBase扫…

国赛大纲解读

1. 第一部分,是针对5G基础知识的掌握,第二部分是人工智能基本算法的掌握,就是人工智能的应用,用5G+人工智能(AI算法)进行网络优化的问题,要有网络优化的基础知识,比如说:某个区域的覆盖问题,覆盖特别差,但有数据,覆盖电频,srp值这些数据给你,根据数据来判断是…

Rabbitmq消息顺序的问题以及解决方案

1.1消息顺序的场景 场景1&#xff1a;一个queue&#xff0c;多个consumer 一个queue&#xff0c;有多个consumer去消费&#xff0c;这样就会造成顺序的错误&#xff0c;consumer从MQ里面读取数据是有序的&#xff0c;但是每个consumer的执行时间是不固定的&#xff0c;无法保…

1-28 核心类库(四)

一 BigDecimal类(会用) 1.作用:用来进行金融类项目中的数据的精确计算 2. import java.math.BigDecimal; import java.math.RoundingMode;public class BigDecimalTest {public static void main(String[] args) {//一定要字符串 int类型的答案不一定准BigDecimal bd1new B…

专题二_滑动窗口(1)

目录 209. 长度最小的子数组 解析 题解 3. 无重复字符的最长子串 解析 题解 1004. 最大连续1的个数 III 解析 题解 209. 长度最小的子数组 209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 解析 题解 class Solution { public:int minSubArrayLen(int…

JAVA WEB 能够实现整个文件夹的上传下载吗?

导入项目&#xff1a; 导入到Eclipse&#xff1a;导入项目 导入到IDEA&#xff1a;导入项目 springboot统一配置&#xff1a;springboot-配置 下载示例&#xff1a; https://gitee.com/xproer/up6-jsp-eclipse/tree/6.5.40/ 工程 NOSQL NOSQL示例不需要任何配置&#xff0c;可…

【Java程序员福音】国外Java 程序员开发常用的工具(全)

Java是一门开源语言&#xff0c;所以可以选择的开发环境很多&#xff0c;你适合哪一个呢&#xff1f;整理了一些Java程序员开发常用的工具&#xff0c;需要的同学可以收藏。 1、免费开源Eclipse Eclipse最初是由IBM公司开发的替代商业软件Visual Age for Java的下一代IDE开发环…

深入浅出:探索Hadoop生态系统的核心组件与技术架构

目录 前言 HDFS Yarn Hive HBase Spark及Spark Streaming 书本与课程推荐 关于作者&#xff1a; 推荐理由&#xff1a; 作者直播推荐&#xff1a; 前言 进入大数据阶段就意味着 进入NoSQL阶段&#xff0c;更多的是面向OLAP场景&#xff0c;即数据仓库、BI应用等。 …

【Ubuntu】Ubuntu LTS 稳定版更新策略

1、确保下载环境 sudo apt update && sudo apt upgrade -y sudo apt autoremove 2、安装更新管理器 sudo apt install update-manager-core -y 3、设置只更新稳定版 sudo vim /etc/update-manager/release-upgrades 4、开始更新&#xff0c;耐心等待 sudo do-re…

iOS开发进阶(十):viewController生命周期讲解

文章目录 一、生命周期二、注意事项案例讲解 一、生命周期 viewController有自己的生命周期&#xff0c;其生命周期如下图&#xff1a; init - 初始化程序&#xff1b;loadView - 在UIViewController对象的view被访问且为空的时候调用&#xff1b;viewDidLoad - 视图加载完成后…