优秀的编程知识分享平台

网站首页 > 技术文章 正文

C# - 字符串及其三大特性 040(c# c++ 字符串)

nanyue 2024-09-15 23:29:40 技术文章 4 ℃

对字符串的操作到目前为止还只是対字符串数据的连接(+)转换和输出这些基础应用

字符串是一个特殊的引用类型,字符串类型还有非常多的其他操作,如查找文本文件中某些文字,统计特定字符/字符串等等

字符串可以看做是一个只读的字符数组,因此可以通过下标循环遍历

 string str1 = "我爱北京天安门";
 //使用下标访问字符串,就可以得到一个字符类型的数据
 char a = str1[0];//我
 //str1.Length 获取字符串的字符个数    
 for (int i = 0; i < str1.Length; i++)
 {
     Console.WriteLine(str1[i]);
 }
 Console.ReadKey();

因为是只读字符数组所以不可更改,因为它是只读属性的

说过字符串方法可以将其变为可写的字符数组,还可以用来统计指定(或用户输入)的字符串中各个字符的个数

字符串特性

1 字符串具有不可变性(也有的叫做恒定性)

int[] num = { 8 };
num[0] = 80;
string str = "我爱"; 
Console.WriteLine(str);
str += "北京";
Console.WriteLine(str);
str += "天安门";
Console.WriteLine(str);
Console.WriteLine("num={0}  str={1}", num[0], str);
Console.ReadKey();

通过复合运算符的赋值操作发现更改了字符串变量的值,貌似被"打脸"了,但是赋值操作并不能推翻“字符串不可变性”中的不可变

可以为变量赋一个全新的值,但出于性能方面考虑,没有提供修改字符串内容的机制

不可变性是指字符串对象的内容不可改变,改变的是栈中对应堆的引用的地址,因此导致赋值结果在改变;

所以说字符串是变量的是从赋值结果来说;说字符串是常量的是从字符串内容

只是上面51,53,55 3行代码在内存堆中就产生了5个字符串对象在内存栈,堆中的变化

数组num[0]都是对同一对象的内容进行修改

str每次+=操作

在栈中str栈的地址不变,改变的是指向堆的地址,因此str赋值才会显现改变

在堆中并不会在原有字符串str上进行操作而是产生一个新的对象并将str指向新对象的地址,旧的对象没有被引用了就成了堆中待GC进行垃圾回收的资源,至于什么时候回收,说到垃圾回收时再细说

这里的"垃圾"指的是程序运行时堆中没有被引用的变量,对象等

因此在有大量字符串拼接时,短时间内会产生大量垃圾,影响性能有内存溢出危险,

2 字符串池(或字符串留用池)主要针对字符串常量

string str1 = "字符串池";
string str2 = "字符串池";
 str1 = str1 + str2;
Console.WriteLine("{0} {1}");
Console.ReadKey();

当程序中有多个相同字符内容的字符串常量时,不是立马创建新对象存储其值而是先在字符串池中查找是否有相同字符的字符串常量,如果有就会指向对中已有的字符串常量,如果没有才会创建新的字符串常量

不会因此产生程序混乱的原因就是因为字符串具有的不可变的特性(由查看str1=str1+str2的堆地址可知)

上面操作不会留有程序垃圾,因为两个字符串常量都有被引用

3 字符串拘留池 常量变量皆可使用,主要针对变量(了解即可)

没有使用字符串拘留池的特性,即使字符串变量的字符相同也会创建新的字符串常量,基于此类状况,.Net为字符串类型又提供了一个字符串拘留的机制

字符串Intern()方法作用相当于将拼接的字符串变为字符串常量留在了字符串池中,下次再有拼接相同字符的字符串,不会创建新的字符串常量,直接指向字符串池中的字符串常量,因为每次创建新的对象会消耗大量的内存

 ////没有使用字符串拘留池
 //string str1 = "我爱";
 //string str2 = "北京";
 //string str3 = "天安门";
 //string str5 =str1 + str2 + str3;
 //string str6 = str1 + str2 + str3;
 ////使用快捷键进行断点调试
 ////将光标放在将要调试暂停的行按下面快捷键即可

 //使用字符串拘留池
 string str1 = "我爱";
 string str2 = "北京";
 string str3 = "天安门";
 //拘留拼接的字符串
 string str5 = string.Intern(str1 + str2 + str3);
 string s1 = "我爱北京";
 string s2 = "天安门";
 //判断堆中是否有相同字符的字符串常量
 string str6 = string.IsInterned(s1 + s2);
 Console.ReadKey();

小结

1)了解字符串具有不可变性的特殊性;了解字符串常量在栈堆的变化,理解其底层逻辑,

2)理解掌握前两个特性,了解第三个特性(一般**必有的面试题...)

3)小量的字符串拼接还可以使用,大量的拼接操作会有专门的类与方法解决

如声明变量,一次声明一个或者多个同类型变量太麻烦,推出了枚举,结构,枚举与结构不能使用循环,推出了数组,数组不能添加,删除元素推出集合类型等,总有新方法来解决

最近发表
标签列表