文章目录
C++中的字符串和字符串字面量是日常编程中经常使用的概念。字符串在C++中有两种主要形式:C风格的字符串(以字符数组表示)和标准库中的std::string
类型。字符串字面量则是程序中直接定义的字符串,如"Hello, World!"
。下面我们将详细讲解这两方面的知识。
一、C风格字符串
1. 定义与特点
C风格字符串是以char
数组形式表示的字符序列,并以空字符 \0
结尾。这个空字符标志着字符串的结束。
char str[] = "Hello";
在这个例子中,str
是一个包含 "Hello"
的字符数组,实际上它的大小为6,因为包含了一个额外的 \0
。
2. 字符串的初始化
可以通过字符数组或指向字符的指针来初始化C风格字符串:
char str1[] = "Hello";
char* str2 = "Hello";
str1
是一个字符数组,存储在栈上,允许修改字符串内容。str2
是一个指针,指向常量字符串字面量,存储在只读内存中,不能修改。
str1[0] = 'h'; // 合法
// str2[0] = 'h'; // 错误,修改只读内存中的字符串会导致未定义行为
3. 常见操作
C风格字符串使用函数库<cstring>
中的函数进行操作:
strlen
:获取字符串长度(不包括\0
)。strcpy
:拷贝字符串。strcat
:连接字符串。strcmp
:比较字符串。
#include <iostream>
#include <cstring>
int main() {
char str1[20] = "Hello";
char str2[] = "World";
strcat(str1, str2); // 连接str2到str1,str1变为"HelloWorld"
std::cout << strlen(str1) << std::endl; // 输出字符串长度(10)
return 0;
}
二、std::string
类型
C++标准库提供了std::string
类,用于处理更为安全和方便的字符串操作。std::string
是一个封装好的类,提供了丰富的字符串操作方法。
1. 定义与初始化
std::string
的初始化比C风格字符串更直观,可以通过直接赋值字符串字面量来完成:
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World!";
std::cout << str << std::endl; // 输出 "Hello, World!"
return 0;
}
2. 字符串操作
std::string
提供了一系列操作方法,可以直接使用这些方法来修改、查询字符串内容:
length()
:返回字符串的长度。append()
:在字符串末尾追加内容。substr()
:返回子串。find()
:查找子串的索引位置。replace()
:替换子串。
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, ";
str.append("World!"); // 追加字符串
std::cout << str << std::endl; // 输出 "Hello, World!"
std::string sub = str.substr(7, 5); // 截取子串,从第7个字符开始,长度为5
std::cout << sub << std::endl; // 输出 "World"
return 0;
}
3. std::string
与C风格字符串的互操作
std::string
和 C风格字符串可以通过成员函数进行互操作:
- 使用
c_str()
或data()
方法获取C风格字符串。 - 通过构造函数将C风格字符串转换为
std::string
。
std::string str = "Hello";
const char* cStr = str.c_str(); // 转换为C风格字符串
4. 自动管理内存
与C风格字符串不同,std::string
会自动管理其内存,用户无需手动分配或释放内存。这大大减少了内存泄漏的风险。
三、字符串字面量
字符串字面量是直接出现在代码中的字符串,由双引号""
括起来,并以const char[]
的形式存储在程序的只读内存中。
const char* str = "Hello, World!";
1. 多种字符串字面量
C++支持多种字符串字面量,包括:
- 普通字符串:
"Hello"
- 宽字符字符串:
L"Hello"
- UTF-8字符串:
u8"Hello"
- UTF-16字符串:
u"Hello"
- UTF-32字符串:
U"Hello"
- 原始字符串:保留转义字符:
R"(Line 1\nLine 2)"
std::string raw_str = R"(Line 1\nLine 2)";
std::cout << raw_str << std::endl; // 输出 "Line 1\nLine 2",转义字符不会生效
2. 字符串字面量与std::string
虽然字符串字面量是const char[]
,但可以轻松转换为std::string
:
std::string str = "Hello, World!"; // 字符串字面量被隐式转换为std::string
四、总结
- C风格字符串:使用字符数组或指针来表示,以
'\0'
结束,需要手动管理内存。 std::string
:C++标准库的字符串类,提供了丰富的操作方法,自动管理内存,更加安全和高效。- 字符串字面量:代码中的直接字符串表示,存储在只读内存中。
通过合理使用std::string
与C风格字符串,并理解字符串字面量的概念,能让C++程序在处理字符串时更加高效、易读和安全。
注意事项
const char* name = "Cherno"
在C++中,字符串字面量,例如 "Cherno"
,默认是存储在只读内存中的。当你使用 const char*
来声明一个指针指向该字符串字面量时,const
修饰符保证你不会通过指针去修改该字符串的内容,从而避免编译错误或运行时的未定义行为。
具体地看:
const char* name = "Cherno"; // 合法,name 指向一个只读的字符串字面量
这个声明中的 const
意味着 name
指向的内容是不可修改的,因此不能通过 name
修改 "Cherno"
这个字面量。尝试修改会导致编译错误。
如果你去掉 const
,代码可能会编译通过,但在尝试修改字符串时会出现运行时错误或未定义行为,因为你试图修改只读内存中的数据:
char* name = "Cherno"; // 这在一些编译器中会产生警告,但有时可能会编译通过
name[0] = 'B'; // 未定义行为,可能导致程序崩溃
因此,使用 const
是正确且安全的做法,可以防止意外修改只读的字符串字面量。没有 const
时,编译器会认为你想修改这块内存,而这通常是不允许的行为。
为了确保代码的健壮性和安全性,建议始终使用 const
修饰指向字符串字面量的指针。