C++ —— string容器(上)
- string 容器的优点
- string 的构造函数
- 示例代码
string 容器的优点
string
是字符容器
,内部维护了一个动态的字符数组。
与普通的字符数组相比,string
容器有三个优点:
- 使用的时候,
不必考虑
内存分配
和释放
的问题; 动态
管理内存(可扩展);- 提供了大量操作容器的
API
。
string 的构造函数
缺点是效率略有降低,占用的资源也更多。string
类是std::basic_string
类模板的一个具体化版本的别名。
NBTS
(null-terminated string):C
风格的字符串(以空字符0
结束的字符串)。
string
类有七个
构造函数(C++11新增了两个,前三个用的多):
string();
创建一个长度为0
的string
对象(默认构造函数)。string(const char *s);
将string
对象初始化为s
指向的NBTS
(转换函数)。string(const string &str);
将string
对象初始化为str
(拷贝构造函数)。string(const char *s,size_t n);
将string
对象初始化为s
指向的地址后n
字节的内容。string(const string &str, size_t pos=0, size_t n=npos);
将sring
对象初始化为str
从位置pos
开始到结尾的字符(或从位置pos
开始的n
个字符)。template<class T> string(T begin,T end);
将string
对象初始化为区间[begin,end]
内的字符,其中begin
和end
的行为就像指针,用于指定位置,范围包括begin
在内,但不
包括end
。string(size_t n,char c);
创建一个由n
个字符c
组成的string
对象。
示例代码
直接看示例代码更加清楚:
#include <iostream>
using namespace std;
int main() {
// 1)string(); // 创建一个长度为0的string对象(默认构造函数)。
string s1;
cout << "s1 = " << s1 << endl; // 因为容器是空的,所以输出空:s1 =
cout << "s1.size() = " << s1.size() << endl; // 输出:0
cout << "s1.capacity() = " << s1.capacity() << endl; // 输出:15
cout << "容器动态数组的首地址:" << (void*)s1.c_str() << endl;
// 容器动态数组的首地址:0x7ffd29eb5890
s1 = "qwewvfwfe235dery13";
cout << "s1 = " << s1 << endl;
cout << "s1.size() = " << s1.size() << endl; // 输出:18
cout << "s1.capacity() = " << s1.capacity() << endl; // 输出:30
cout << "容器动态数组的首地址:" << (void*)s1.c_str() << endl;
// 容器动态数组的首地址:0x5609c668bec0
// 2)string(const char *s); // 将string对象初始化为s指向的NBTS(转换函数)。
string s2("aaaaaaaaa");
cout << "s2 = " << s2 << endl; // 输出:aaaaaaaaa
cout << (void*)s2.c_str() << endl; // 0x7ffd29eb58b0
string s3 = "bbbbbbbbb";
cout << "s3 = " << s3 << endl; // 输出:bbbbbbbbb
cout << (void*)s3.c_str() << endl; // 0x7ffd29eb58d0
// // 3)string(const string &str); // 将string对象初始化为str(拷贝构造函数)。
string s4(s3);
cout << "s4 = " << s4 << endl; // 输出:bbbbbbbbb
cout << (void*)s4.c_str() << endl; // 0x7ffd29eb58f0 与s3不同
string s5 = s2;
cout << "s5 = " << s5 << endl; // 输出:aaaaaaaaa
cout << (void*)s5.c_str() << endl; // 0x7ffd29eb5910 与s2不同
// // 4)string(const char *s,size_t n); // 将string对象初始化为s指向的地址后n字节的内容。
string s6("1234567890", 5);
cout << "s6 = " << s6 << endl; // 输出:12345
string s7("abcde", 50);
cout << "s7 = " << s7 << endl; // 输出:abcde再加上一堆乱码
// // 5)string(const string &str,size_t pos=0,size_t n=npos); // 将sring对象初始化为str从位置pos开始到结尾的字符(或从位置pos开始的n个字符)。
string s = "0123456789";
string s8(s, 3);
cout << "s8 = " << s8 << endl; // s8 = 3456789
string s9(s, 5, 3);
cout << "s9 = " << s9 << endl; // s9 = 567
// // 6)template<class T> string(T begin,T end); // 将string对象初始化为区间[begin,end]内的字符,其中begin和end的行为就像指针,用于指定位置,范围包括begin在内,但不包括end。(以后再补充)
// // 7)string(size_t n,char c); // 创建一个由n个字符c组成的string对象。
string s10(10, 'a');
cout << "s10 = " << s10 << endl; // 输出:aaaaaaaaaa
cout << "s10.size() = " << s10.size() << endl; // 输出:10
cout << "s10.capacity() = " << s10.capacity() << endl; // 输出:15
return 0;
}
capacity()
获取容器的当前容量
。意思是,如果不重新分配内存,当前可以存放字符的总个数。
size()
获取容器
中数据的大小
,意思是,里面已经
存放了多少个字符。
往string
容器中存放数据时,如果数据多大就分配多大的内存,那么每次扩展容器时,都要重新分配内存,效率低。所以,合理的做法是预先分配比数据实际大小更多的空间,避免过于频繁的分配和释放内存。
扩展
空间时,先分配更大
的空间,再把内容复制
过去,最后释放
以前的空间。所以,s1
扩展前后首地址不一样。
感谢浏览,一起学习!