浅谈C++中的String类

本文详细介绍了C++标准库中的String类,包括如何创建、追加、赋值、比较字符串等基本操作,以及如何利用内置函数进行字符串的查找、替换、截取等高级操作。

C++学习笔记4
该系列内容来源于: 中国大学MOOC 北京邮电大学 C++程序设计(面向对象进阶)

浅谈C++中的String类

The C++ string Class

C++ 使用 string 类处理字符串

string类中的函数

  1. 构造

  2. 追加(append

  3. 赋值(assign

  4. 位置与清除(atcleareraseempty

  5. 长度与容量(size

  6. 比较(compare

  7. 子 串(substr

  8. 搜索(find

  9. 插入与替换(insertreplace

  10. 运算符([ ]=+等)

建议在 cppreference 网站上仔细阅读这些函数的用法,或者在编程时注意IDE的智能提示。

注意事项

操作string对象中的字符串内容时,有时会用到“index”。

很多string的函数接受两个数字参数: index, n

  1. index:从index号位置开始

  2. n:之后的n个字符

创建 string 对象

  • 用无参构造函数创建一个空字串
  • 由一个字符串常量字符串数组创建string对象
string a; // 空字符串

string message{ "Aloha World!" };

char charArray[] = {'H', 'e', 'l', 'l', 'o', '\0'};

string message1{ charArray };

追加字符串

一系列append的重载函数可以将新内容附加到一个字符串中。

string s1{ "Welcome" };

s1.append( " to C++" ); // appends " to C++" to s1

cout << s1 << endl; // s1 now becomes Welcome to C++

string s2{ "Welcome" };

s2.append( " to C and C++", 3, 2 ); // appends " C" to s2

cout << s2 << endl; // s2 now becomes Welcome C

string s3{ "Welcome" };

s3.append( " to C and C++", 5); // appends " to C" to s3

cout << s3 << endl; // s3 now becomes Welcome to C

string s4{ "Welcome" }; 

s4.append( 4, 'G' ); // appends "GGGG" to s4

cout << s4 << endl; // s4 now becomes WelcomeGGGG

为字符串赋值

一系列assign的重载函数可以将一个字符串赋以新内容

string s1{ "Welcome" };

s1.assign( "Dallas" ); // assigns "Dallas" to s1

cout << s1 << endl; // s1 now becomes Dallas

string s2{ "Welcome" };

s2.assign( "Dallas, Texas", 1, 3 ); // assigns "all" to s2

cout << s2 << endl; // s2 now becomes all

string s3{ "Welcome" };

s3.assign( "Dallas, Texas", 6 ); // assigns "Dallas" to s3

cout << s3 << endl; // s3 now becomes Dallas

string s4{ "Welcome" };

s4.assign( 4, 'G' ); // assigns "GGGG" to s4

cout << s4 << endl; // s4 now becomes GGGG

位置与清除

  1. at(index): 返回当前字符串中index位置的字符
  2. clear(): 清空字符串
  3. erase(index, n): 删除字符串从index开始的n个字符
  4. empty(): 检测字符串是否为空
string s1{ "Welcome" };

cout << s1.at(3) << endl; // s1.at(3) returns c

cout << s1.erase(2, 3) << endl; // s1 is now Weme

s1.clear(); // s1 is now empty

cout << s1.empty() << endl; // s1.empty returns 1 (means true)

比较字符串

compare() 函数用于比较两个字符串。它与C语言中的 strcmp() 函数很像。

string s1{ "Welcome" };

string s2{ "Welcomg" };

cout << s1.compare(s2) << endl; // returns -2

cout << s2.compare(s1) << endl; // returns 2

cout << s1.compare("Welcome") << endl; // returns 0

获取子串

at() 函数用于获取一个单独的字符;

substr() 函数则可以获取一个子串

string s1{ "Welcome" };

cout << s1.substr(0, 1) << endl; // returns W;  从0号位置开始的1个字符

cout << s1.substr(3) << endl; // returns come;  从3号位置直到末尾的子串

cout << s1.substr(3, 3) << endl; // returns com;从3号位置开始的3个字符

搜索字符串

find() 函数可以在一个字符串中搜索一个子串或者一个字符

string s1{ "Welcome to C++" };

cout << s1.find("co") << endl; // returns 3; 返回子串出现的第一个位置

cout << s1.find("co", 6) << endl; // returns -1 从6号位置开始查找子串出现的第一个位置

cout << s1.find('o') << endl; // returns 4    返回字符出现的第一个位置

cout << s1.find('o', 6) << endl; // returns 9   从6号位置开始查找字符出现的第一个位置

插入和替换字符串

  1. insert():将某个字符/字符串插入到当前字符串的某个位置

  2. replace():将本字串从某个位置开始的一些字符替换为其它内容

string s1("Welcome to C++");

s1.insert(11, "Java and ");

cout << s1 << endl; // s1 becomes Welcome to Java and C++

string s2{ "AA" };

s2.insert(1, 4, 'B'); //在1号位置处连续插入4个相同字符

cout << s2 << endl; // s2 becomes to ABBBBA

string s3{ "Welcome to Java" };

s3.replace(11, 4, "C++"); //从11号位置开始向后的4个字符替换掉。注意'\0'

cout << s3 << endl; // returns Welcome to C++ 

字符串运算符

OperatorDescription
[ ]用数组下标运算符访问字符串中的字符
=将一个字符串的内容复制到另一个字符串
+连接两个字符串得到一个新串
+=将一个字符串追加到另一个字符串末尾
<<将一个字符串插入一个流
>>从一个流提取一个字符串,分界符为空格或者空结束符
==, !=, <, <=, >, >=用于字符串比较
string s1 = "ABC"; // The = operator

string s2 = s1;    // The = operator

for (int i = s2.size() - 1; i >= 0; i--)

    cout << s2[i]; // The [] operator

 

string s3 = s1 + "DEFG"; // The + operator

cout << s3 << endl; // s3 becomes ABCDEFG

 

s1 += "ABC";

cout << s1 << endl; // s1 becomes ABCABC

 

s1 = "ABC";

s2 = "ABE";

cout << (s1 == s2) << endl; // Displays 0 

cout << (s1 != s2) << endl; // Displays 1 

cout << (s1 >  s2) << endl; // Displays 0 

cout << (s1 >= s2) << endl; // Displays 0 

cout << (s1 <  s2) << endl; // Displays 1 

cout << (s1 <= s2) << endl; // Displays 1 
<think>首先,用户的问题是:“我想了解C++中std::string的析构函数的相关信息 请问C++ std::string析构函数std::string::~string的详细介绍”。所以,我需要专注于std::string的析构函数。 回想系统级指令: - 所有行内数学表达式必须使用$...$格式,但在这个主题中,可能没有数学表达式,所以我不需要担心。 - 独立公式必须使用$$...$$并单独成段。 - LaTeX语法正确。由于问题涉及编程,可能主要是代码和文本,所以LaTeX可能不常用,但如果有数学表达式,我会遵守。 - 使用中文回答。 - 生成相关问题。 - 引用段落末尾添加引用标识。 引用内容摘要: - 引用[1]: 介绍std::string,包括底层实现。 - 引用[2]: 详细介绍std::string,包括特点和操作。 - 引用[3]: 列出构造函数和析构函数。具体提到析构函数:析构函数是~string(),用于销毁对象并释放内存。 - 引用[4]: 讨论insert函数。 - 引用[5]: 讨论STL版本和std::string的底层实现,提到浅拷贝和引用计数。 从引用[3]中,它明确指出析构函数:析构函数是~string(),用于销毁对象并释放内存。引用[5]谈到std::string的底层实现,提到使用引用计数(copy-on-write),在析构时,引用计数会减少,如果计数为零,则释放内存。 我的回答需要基于这些引用,但用户说“上述引用仅供参考”,所以我应该优先参考用户上一次的问题和我的回答。但在上下文中,这是第一个问题,用户直接问析构函数的详细信息。 结构化回答: - 回答应清晰,逐步解决问题。 - 保证真实可靠,基于标准C++知识。 内容大纲: 1. **介绍std::string析构函数**:解释什么是析构函数,它在std::string中的作用。 - 析构函数名为~string()。 - 当对象的生命周期结束时自动调用(例如,对象离开作用域或显式删除)。 - 主要作用是释放std::string对象分配的内存资源。 2. **行为细节**: - 释放内部存储字符串的缓冲区。 - 根据底层实现,使用引用计数(copy-on-write),在析构时减少引用计数;如果计数为零,则释放内存。 - 这是自动的,程序员不需要手动释放内存。 3. **示例或代码**:提供简单代码示例演示析构函数的调用。 4. **引用相关部分**:在回答中引用提供的信息。 - 例如,引用[3]提到析构函数。 - 引用[5]讨论底层实现。 5. **注意事项**:讨论内存管理、异常安全等(如果相关)。 6. **生成相关问题**:在末尾添加相关问题。 用中文回答。 最终回答结构: - 开头介绍析构函数。 - 详细解释行为和实现。 - 代码示例。 - 结尾添加相关问题。 </think>### C++ std::string析构函数详解 在C++中,`std::string`是标准模板库(STL)提供的用于处理字符串的,定义在`<string>`头文件中。它的析构函数`std::string::~string`在对象生命周期结束时自动调用,负责清理资源并释放内存。以下基于用户提供的引用和C++标准规范,详细介绍析构函数的行为、实现原理和相关注意事项。我会逐步解答,确保内容真实可靠。 #### 1. **析构函数的基本作用** - **定义和调用时机**:`std::string::~string`是`std::string`的析构函数,语法为`~string()`。它在对象被销毁时自动调用,例如: - 当对象离开作用域(如函数结束)。 - 当对象被显式删除(如使用`delete`操作符)。 - 在容器(如`std::vector<std::string>`)被销毁时调用。 - **核心功能**:析构函数的主要任务是释放`std::string`对象内部管理的动态内存(即存储字符串的字符数组缓冲区)。这确保了内存泄漏的避免,因为对象不再需要时,资源会自动回收[^3]。 - **自动管理**:相比于C风格字符串(需手动`delete[]`),`std::string`通过析构函数实现自动内存管理,提高了安全性和便捷性[^2]。 #### 2. **析构函数的行为和底层实现** - **内存释放机制**: - `std::string`内部维护一个动态分配的字符缓冲区(通常是一个字符数组)。析构函数调用时,会释放这个缓冲区。 - 在早期的C++版本(如C++98),`std::string`实现使用“写时复制”(Copy-On-Write, COW)机制。这意味着多个`std::string`对象可能共享同一块内存(浅拷贝),析构函数通过减少引用计数来管理资源:如果引用计数降为零,则释放内存;否则,仅减少计数而不释放[^5]。 - 在较新版本(如C++11及以上),为优化性能,许多实现(如GCC和Clang)移除了COW,改用“小字符串优化”(SSO)。在SSO下,短字符串直接存储在对象内部(栈内存),不动态分配;长字符串使用堆内存。析构函数智能判断:如果是动态分配的内存,则调用`delete[]`释放;否则,无操作。 - **示例代码演示析构调用**: ```cpp #include <iostream> #include <string> void exampleFunction() { std::string s1 = "Hello, World!"; // 构造函数创建对象 // 当exampleFunction结束时,s1离开作用域,析构函数自动调用 } // 析构函数~string()在此处调用,释放s1的内存 int main() { std::string* s2 = new std::string("Dynamic string"); delete s2; // 显式调用析构函数并释放内存 return 0; } ``` 在上例中,`s1`在函数结束时自动销毁,`s2`通过`delete`触发析构。 - **异常安全**:C++标准规定析构函数为`noexcept`(不抛出异常)。这意味着析构操作是安全的,不会中断程序流程,即使在异常发生时也能保证资源释放[^3]。 #### 3. **注意事项和最佳实践** - **避免双重删除**:由于析构函数自动管理内存,程序员不应手动释放`std::string`的内部缓冲区(如访问`c_str()`后调用`delete`),否则会导致未定义行为。 - **性能影响**:析构函数的开销很低(O(1)时间),因为它只涉及内存释放操作。但在高频调用的场景(如大量临时字符串),可能影响性能;建议使用移动语义(C++11引入)来优化。 - **版本兼容性**:析构函数行为在不同C++标准版本中一致,但底层实现细节(如COW vs SSO)随STL版本变化: - C++98/03:常用COW机制,析构函数处理引用计数[^5]。 - C++11及以上:普遍采用SSO,析构函数更高效;同时,移动构造函数优化了资源转移,减少析构调用次数[^3]。 - **与构造函数关联**:析构函数是对象生命周期的终点,与构造函数(如`string(const char*)`)配对使用,确保资源完整释放[^3]。 总之,`std::string::~string`是C++内存管理的关键部分,它简化了字符串处理,避免了常见错误(如内存泄漏)。通过自动调用,开发者可以专注于业务逻辑,而无需手动管理资源[^2][^3]。 相关问题: 1. std::stringC++11中如何通过移动语义优化析构性能? 2. 小字符串优化(SSO)的具体实现如何影响std::string的析构函数行为? 3. 在多线程环境中,std::string析构函数是否安全? 4. 如何自定义一个来实现似std::string的自动内存管理? 5. C++中其他STL容器(如std::vector)的析构函数工作原理是什么?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值