返回介绍

第1章 面试的流程

第2章 面试需要的基础知识

第3章 高质量的代码

第4章 解决面试题的思路

第5章 优化时间和空间效率

第6章 面试中的各项能力

第7章 两个面试案例

2.3.2 字符串

发布于 2024-08-21 20:57:09 字数 2083 浏览 0 评论 0 收藏 0

字符串是由若干字符组成的序列。由于字符串在编程时使用的频率非常高,为了优化,很多语言都对字符串做了特殊的规定。下面分别讨论C/C++和C#中字符串的特性。

C/C++中每个字符串都以字符'\0'作为结尾,这样我们就能很方便地找到字符串的最后尾部。但由于这个特点,每个字符串中都有一个额外字符的开销,稍不留神就会造成字符串的越界。比如下面的代码:

我们先声明一个长度为10的字符数组,然后把字符串"0123456789"复制到数组中。"0123456789"这个字符串看起来只有10个字符,但实际上它的末尾还有一个'\0'字符,因此它的实际长度为11个字节。要正确地复制该字符串,至少需要一个长度为11个字节的数组。

为了节省内存,C/C++把常量字符串放到单独的一个内存区域。当几个指针赋值给相同的常量字符串时,它们实际上会指向相同的内存地址。但用常量内存初始化数组,情况却有所不同。下面通过一个面试题来学习这一知识点。运行下面的代码,得到的结果是什么?

str1和str2是两个字符串数组,我们会为它们分配两个长度为12个字节的空间,并把"hello world"的内容分别复制到数组中去。这是两个初始地址不同的数组,因此str1和str2的值也不相同,所以输出的第一行是str1 and str2 are not same。

str3和str4是两个指针,我们无须为它们分配内存以存储字符串的内容,而只需要把它们指向"hello world在内存中的地址就可以了。由于"hello world是常量字符串,它在内存中只有一个拷贝,因此str3和str4指向的是同一个地址。所以比较str3和str4的值得到的结果是相同的,输出的第二行是str3 and str4 are same。

在C#中,封装字符串的类型System.String有一个非常特殊的性质:String中的内容是不能改变的。一旦试图改变String的内容,就会产生一个新的实例。请看下面的C#代码:

虽然我们对str做了ToUpper和Insert两个操作,但操作的结果都是生成一个新的String实例并在返回值中返回,str本身的内容都不会发生改变,因此最终str的值仍然是"hello"。由此可见,如果试图改变String的内容,改变之后的值只可以通过返回值得到。用String作连续多次修改,每一次修改都会产生一个临时对象,这样开销太大会影响效率。为此C#定义了一个新的与字符串相关的类型StringBuilder,它能容纳修改后的结果。因此如果要连续多次修改字符串内容,用StringBuilder是更好的选择。

和修改String内容类似,如果我们试图把一个常量字符串赋值给一个String实例,也不是把String的内容改成赋值的字符串,而是生成一个新的String实例。请看下面的代码:

在上面的代码中,我们先判断String是值类型还是引用类型。类型String的定义是public sealed class String {...}。既然是class,那么String自然就是引用类型。接下来在方法ModifyString里,对text赋值一个新的字符串。我们要记得text的内容是不能被修改的。此时会先生成一个新的内容是"world"的String实例,然后把text指向这个新的实例。由于参数text没有加ref或者out,出了方法ModifyString之后,text还是指向原来的字符串,因此输出仍然是"hello"。要想实现出了函数之后text变成"world"的效果,我们必须把参数text标记ref或者out。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文