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

news2024/11/17 16:46:34

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

乐维更改IP地址

1.1 系统IP调整 vim /etc/sysconfig/network-scripts/ifcfg-ens1921.2 Web相关服务IP变更 1.2.1 编辑/itops/nginx/html/lwjkapp/.env文件,更改ZABBIXSERVER、ZABBIXRPCURL、DB_HOST中的IP 1.2.2 进入/itops/nginx/html/lwjk_app/目录下,执行php bin/manager process-conso…

『Apisix安全篇』APISIX 加密传输实践:SSL/TLS证书的配置与管理实战指南

🚀『Apisix系列文章』探索新一代微服务体系下的API管理新范式与最佳实践 【点击此跳转】 📣读完这篇文章里你能收获到 🌟 了解SSL/TLS证书对于网络通信安全的重要性和基础概念。🔧 掌握在APISIX中配置SSL/TLS证书的基本步骤和方…

嵌入式开发——基础电路知识

1. 电路知识 1.1. 驱动能力 IC是数字逻辑芯片,其输出的是逻辑电平。逻辑电平0表示输出电压低于阈值电压,逻辑1表示输出电压高于阈值电压。负载则是被驱动的电路或元件,负载大小则指负载的电阻大小。 驱动能力主要表现在几个方面&#xff1…

centos2anolis

我的centos7原地升级到anolis7记录 注意:如果是桌面版请先卸载firefox,否则so文件冲突。 参考: CentOS 7和8Linux系统迁移到国产Linux龙蜥Anolis OS 8手册_disable pam_pkcs11 module in pam configuration-CSDN博客 关于 CentOS 迁移龙蜥…

【pytest、playwright】allure报告生成视频和图片

目录 1、修改插件pytest_playwright 2、conftest.py配置 3、修改pytest.ini文件 4、运行case 5、注意事项 1、修改插件pytest_playwright pytest_playwright.py内容如下: # Copyright (c) Microsoft Corporation. # # Licensed under the Apache License, Ver…

Prompt Engineering的4 种方法

此为观看视频 4 Methods of Prompt Engineering 后的笔记。 从通用模型到专用模型,fine tuning(微调)和prompt engineering(提示工程)是2种非常重要的方法。本文深入探讨了prompt engineering的4种方法。 首先&#…

Trello国内替代工具有哪些?分享5款

盘点5款类似Trello的本地部署项目管理工具:1.PingCode;2.Worktile;3.Teambition;4.redmine;5.TAIga.io。 Trello是一款杰出的协作与工作管理应用,专为追踪团队项目、凸显当前活动任务、分配责任人&#xff…

爬虫(Web Crawler)介绍与应用

## 摘要 本文将介绍什么是爬虫(Web Crawler)以及其在信息抓取、数据分析等领域的应用。我们将深入探讨爬虫的工作原理、设计特点以及开发过程中需要考虑的关键问题。 ## 一、什么是爬虫 爬虫是一种自动化程序或脚本,用于从互联网上抓取信息…

计算机组成原理-6-计算机的运算方法

6. 计算机的运算方法 文章目录 6. 计算机的运算方法6.1 机器数的表示6.1.1 无符号数和有符号数6.1.2 有符号数-原码6.1.3 有符号数-补码6.1.4 有符号数-反码6.1.5 有符号数-移码6.1.6 原码、补码、反码的比较 6.2 数的定点表示和浮点表示6.2.1 定点表示6.2.2 浮点表示6.2.3 ΔI…

Lilishop商城(windows)本地部署【docker版】

Lilishop商城(windows)本地部署【docker版】 部署官方文档:LILISHOP-开发者中心 https://gitee.com/beijing_hongye_huicheng/lilishop 本地安装docker https://docs.pickmall.cn/deploy/win/deploy.html 命令端页面 启动后docker界面 注…

保障校园网络安全用堡垒机的几个原因分析

校园,人人都熟悉的地方,梦想知识开始的地方。在互联网数字化快速发展的今天,网络安全的学习环境是非常必要的。所以采购保障校园网络安全工具是必要的。那为什么一定要用堡垒机呢?这里我们一起来简单分析一下原因。 保障校园网络…

CleanMyMac X2024专业免费的国产Mac笔记本清理软件

非常高兴有机会向大家介绍CleanMyMac X 2024这款专业的Mac清理软件。它以其强大的清理能力、系统优化效果、出色的用户体验以及高度的安全性,在Mac清理软件市场中独树一帜。 CleanMyMac X2024全新版下载如下: https://wm.makeding.com/iclk/?zoneid49983 一、主要…

Docker搭建LNMP环境实战(03):VMware安装CentOS

Docker搭建LNMP环境实战(03):VMware安装CentOS 1、创建新的虚拟机,选择CentOS7镜像文件,并启动安装 启动VMware,创建新的虚拟机 图1 选择典型安装即可 选用最大最全的CentOS镜像文件:CentOS-7…

深度好文:解决Ubuntu 18.04安装nvidia显卡驱动,导致内核不匹配:无需重装系统修复内核

深度好文:解决Ubuntu 18.04安装nvidia显卡驱动,导致内核不匹配:无需重装系统修复内核 目录 一、问题描述二、尝试修复三、安装Nvidia驱动和CUDA并配置cuDNN四、总结 一、问题描述 昨天打算更新一下Ubuntu 18.04的显卡驱动,以支持…

element-ui checkbox 组件源码分享

简单分享 checkbox 组件,主要从以下三个方面来分享: 1、组件的页面结构 2、组件的属性 3、组件的方法 一、组件的页面结构 二、组件的属性 2.1 value / v-model 属性,绑定的值,类型 string / number / boolean,无…

存储的过程

一、存储过程 1.1 概述 存储过程可以轻松而高效的去完成这个需求,有点类似shell脚本里的函数 1.2 特点 存储过程在数据库中创建并保存,它不仅仅是 SQL 语句的集合,还可以加入一些特殊的控制结构,也可以控制数据的访问方式。存储过…

web前端面试题----->VUE

Vue的数据双向绑定是通过Vue的响应式系统实现的。具体原理: 1. Vue会在初始化时对数据对象进行遍历,使用Object.defineProperty方法将每个属性转化为getter、setter。这样在访问或修改数据时,Vue能够监听到数据的变化。 2. 当数据发生变化时…

【R语言从0到精通】-1-下载R语言与R最基础内容

在本科,没有人教的情况下,艰难的自学了R语言,因此我想能出一个R语言系列教程,在帮助大家的同时,温故而知新,特别如果你是生物或者医学从业者,那本教程正好合适,因为我也是生物人&…

Microsoft .NET 应用程序性能监控

什么是 .NET监控 Microsoft .NET 监视在确保可以开发和部署应用程序而不必面对性能滞后或中断方面发挥着重要作用。它使用警报、增长趋势报告和数据可视化技术来帮助管理员确保 Microsoft .NET 平台的全天候可用性。Microsoft.NET 性能监视是一种检测性能异常的先发制人方法&a…

2024年腾讯云4核8g服务器并发数、优惠价格、支持多少人在线?

腾讯云4核8G服务器价格:轻量4核8G12M优惠价格646元15个月、CVM S5服务器4核8G配置1437元买1年送3个月。腾讯云4核8G服务器支持多少人同时在线?支持30个并发数,可容纳日均1万IP人数访问。腾讯云百科txybk.com整理4核8G服务器支持多少人同时在线…