[iOS] Three implementations of NSString

Tip: After the article is written, the table of contents can be automatically generated. How to generate it can refer to the help document on the right


foreword

Recently, I was asked by seniors about the three implementation methods of the bottom layer of NSString, but I couldn't answer, so I wrote a blog record


Method to realize

In OC, the NSString type has three implementations, namely

__NSCFConstantString
__NSCFString
NSTaggedPointerString

knowledge introduction

insert image description here

Compilation result:
insert image description here

One thing to note here is that when we use reference counting, we must first turn off our ARC
insert image description here

##Understand the implementation

You can see that we create different types of strings of different lengths in different ways, and we will explain them one by one next.

__NSCFConstantString

Our common understanding of this type is a constant string.
In Objective-C, string literals (such as @"Hello") are treated as constants and stored in the constant data area. It is considered a compile-time constant. It is used to represent string literals, which are determined at compile time and stored as constants in the constant data area at runtime.
The compiler will optimize the string literal into a constant, whose content is determined at compile time, and stored in the constant data area of ​​the executable.
The advantage of this is that it can improve the access efficiency of strings and save memory space, because each identical string literal only needs to be stored in one copy , which means that the addresses of our str1 and str1_ are equal.

At the same time, if the addresses of the two objects we created in the same way are equal, it also proves that he is asingleton

In addition, we can see that its reference count is very large, indicating that instances of this type cannot be released

So here we conclude that constant string is a kind of singleton .
insert image description here

The __NSCFConstantString object is immutable, that is, its content cannot be modified. Since string literals are immutable, they cannot be modified after creation. Objects of type __NSCFConstantString
are designed to be read-only to ensure the immutability of string literals.

We generally generate this type through @“…”, CFSTR(“…”) or stringWithString: method

This object is stored in the string constant area

__NSCFString

Unlike __NSCFConstantString, the __NSCFString object is a subclass of NSString created at runtime, not a string constant. So it gets a reference count of 1 when it is created like any other object.

NSString objects created by methods such as stringWithFormat of NSString are generally of this type.

Such objects are stored on the heap.

In our code we can see:
insert image description here

When we assign the same type of string to different instances through the stringWithFormat method, the addresses of the instances are different, which also indirectly shows the objects stored on the heap. Even if the contents of the two objects are the same, their memory addresses on the heap are also different. Each object is stored in a separate memory space with its own address. This means that when these two objects are accessed through different object references, they are actually accessing different memory addresses.

NSTaggedPointerString

NSTaggedPointerString is a special type of string used in Objective-C to represent shorter string objects.


TaggedPointer means a tagged pointer, which is some optimizations made by Apple for objects such as NSString and NSNumber in a 64-bit environment . Simply speaking, it can be understood that the content pointed to by the pointer is directly placed in the memory address of the pointer variable , because the size of the pointer variable reaches 8 bits in a 64-bit environment,
which is enough to accommodate some smaller-length content. Therefore, the method of tag pointer is used to optimize the storage method of data. It can be seen from his reference count that this product is also a singleton constant object that cannot be released. Created according to the actual situation at runtime.

For NSString objects, when the length of a non-literal constant number or English letter string is less than or equal to 9, it will automatically become the NSTaggedPointerString type. If there are Chinese or other special symbols (possibly non-ASCII characters), it will directly become) __NSCFString type.

This is also reflected in the code example

This object is stored directly in the content of the pointer and can be treated as a pseudo-object.

Three Types of Deep and Shallow Duplication

Let's first review our definition of deep and shallow copying

A shallow copy refers to the creation of a new object that shares a reference to its internal data with the original object. In other words, a shallow copy only copies the object itself, not the data referenced by the object. Thus, the original object and the copy object point to the same memory, and modifications to one affect the other.
In layman's terms, shallow copy is just to create a pointer variable that stores the same address as the copied object, which can also be called pointer copy

A deep copy refers to creating a new object and copying the original object and all the data it references. A deep copy recursively copies all the contents of an object, including other objects that the object references. In this way, the original object and the copy object have independent memory spaces, and their modifications do not affect each other.
In layman's terms, deep copy is to create an object with exactly the same value as the copied object, but their addresses are different, so deep copy can also be called content copy

Shallow copy is to copy the pointer to the original object, so that the reference count of the original object is +1. It can be understood that a new pointer to the original object is created, and a brand new object is not created. And deep copy will not be reference count +1.

insert image description here

Compilation result:
insert image description here

As you can see from the compilation results, the deep and shallow copies of our three implementations of NSString are exactly the same as the deep and shallow copies of our container class objects. As for the principle of deep and shallow copying of container classes, the author will write another blog to describe it.

Here we can also understand why copy is called a pointer copy. When we make a shallow copy of an object of our __NSCFString class, we can see that its reference count has increased by 1. At the same time, because the other two classes are singletons, their reference counts will not increase no matter how they are operated

Another thing to note here is that when we copy the NSString class, all copied objects belong to __NSCFConstantString.

The author solved the problem by using ChatGPT, but its correctness cannot be guaranteed. If there is a mistake in the follow-up learning process, go back and modify it.
insert image description here

Summarize

This article describes the three implementations of NSString, and then summarizes the knowledge learned

1、__NSCFConstantString:

We generally generate this type through @“…”, CFSTR(“…”) or stringWithString: method

This kind of object is stored in the constant area, which is a compile-time constant and a singleton

The advantage is that it can improve the access efficiency of strings and save memory space

2、__NSCFString

NSString objects created by methods such as stringWithFormat of NSString are generally of this type.

He is not a string constant. So it gets a reference count of 1 when it is created like any other object.

Such objects are stored on the heap.

3、NSTaggedPointerString

The NSString object created by NSString's stringWithFormat : and other methods may be of this type, depending on the length of the string.

Numbers or English alphabet characters less than or equal to 9 may become this type, and for Chinese and other special characters, they will directly become the __NSCFString type

It is also a singleton constant object that cannot be released. Created according to the actual situation at runtime.

Such objects are stored directly in the content of the pointer

4. Three types of shallow and deep copy

Comply with the deep and shallow copy principle of container class objects

piece of cake:

1. Why are the objects created with @ and stringWithString methods the same object:

The stringWithString: method is used to create a new string object that is a copy of the passed in string object. And string literals (such as
@"Hello") are already an immutable NSString object and don't need to be copied because they are inherently immutable.

2. Why can't we create these instances directly

In Objective-C, since __NSCFConstantString, __NSCFString, and
NSTaggedPointerString are private classes of the runtime library, instances of them cannot be created directly.
Instead, we can create these implementations indirectly by using objects of type NSString or NSMutableString.

3. What does the private class of the runtime library mean?

In Objective-C, runtime library private classes are classes that are not public or documented in the compiler and official documentation. These classes are the internal implementation details of the runtime library used to support
various functions and features of Objective-C. They are usually not directly exposed to developers, but are encapsulated by public classes and provide higher-level interfaces.

Private classes play an important role in the runtime library and are used to implement core functions such as strings, arrays, collections, memory management, and message passing. These classes may contain lower-level data structures and algorithms used to improve performance, optimize memory footprint, and implement specific language features.

Guess you like

Origin blog.csdn.net/weixin_72437555/article/details/130769750