学习一门编程语言,考察编程语言支持的基本数据结构是很重要的。如果你以前学的C/C++倾向于自己造轮子,或者你有其他语言背景的话,建议重新了解一下C++11 标准库中的数据结构。
字符串 std::string
你可以用 const char* 也就是字符串字面量来构造 std::string ,也可以从 std::string 中获取 C风格字符串的指针(const char*)。
1 2 |
std::string foo = "foo"; foo.c_str(); // const char* |
std::string 是可变的,所以你可以修改 std::string 而不用太担心性能
1 2 3 4 |
std::string result; result += "foo"; result += '@'; result += "example.com"; |
关于不可变字符串,有很多讨论,这里列举一下想要用不可变的“字符串”话,在不用其他库的情况下可以怎么做
- const char* 如果自己分配的字符串数组的话,需要记得delete。字符串字面量的话不用担心。
- const std::string& 给 std::string 加const,严格来说这只是防止修改
- 自己造轮子
std::string 支持 copy 和 move
std::string 的 substr 返回的是 copy 过的子字符串。
C++17开始支持 string_view。在C++17之前想用“字符串视图”的话,你可能要自己构造一个类似下面这种包装结构
1 2 3 4 5 6 7 8 9 10 11 |
struct StringView { std::shared_ptr<std::string> str_ptr_; size_t start_; size_t end_; explicit StringView( std::shared_ptr<std::string>& str_ptr, size_t start, size_t end): str_ptr_{str_ptr}, start_{start}, end_{end} { } }; |
std::string 的 = 是字符串比较,而不是地址比较。
std::string 提供的相关方法不多,现有的比如查找find/rfind
1 2 3 |
std::string foo = "foo"; foo.find('f'); // 0 foo.find('a'); // not found, std::basic_string::npos |
需要注意找不到时返回的不是-1,而是npos,一个特殊的值
std::string 提供了两个获取字符的方法,at 和 [],前者加了范围检查,后者没有
支持用迭代器方式遍历字符串
1 2 3 4 |
std::string foo = "foo"; for(const char& ch: foo) { // do stuff } |
关于UTF-8字符串,可能和 std::string 没有直接关系,但是C++11中的字符串字面量
1 2 |
"foo"; // 1 u8"foo"; // 2 |
1是依赖于系统编码的字符串字面量,2是UTF-8编码的字符串字面量。
std::string 没有直接支持UTF-8的方法,size返回的是字节数,如果你用迭代器遍历的话,是按照逐个byte的方式(虽然类型叫char)