赞
踩
c++ primer plus 第16章string 类和标准模板库,string 类
很多应用程序都需要处理字符串。C语言在stringh(在C++中为cstring)中提供了一系列的字符串函数,很多早期的C++实现为处理字符串提供了自己的类。第4章介绍了ANSIISOC++string类,而第 12章创建了一个不大的 String类,以说明设计表示字符串的类的某些方面。
string 类是由头文件 string 支持的(注意,头文件 string.h和 cstring 支持对 C-风格字符串进行操纵的 C库字符串函数,但不支持 string类)。要使用类,关键在于知道它的公有接口,而 string 类包含大量的方法,其中包括了若干构造函数,用于将字符串赋给变量、合并字符串、比较字符串和访问各个元素的重载运算符以及用于在字符串中查找字符和子字符串的工具等。简而言之,string类包含的内容很多。
先来看 string 的构造函数。毕竟,对于类而言,最重要的内容之一是,有哪些方法可用于创建其对象。程序清单16.1使用了string的7个构造函数(用 ctor 标识,这是传统 C++中构造函数的缩写)。表16.1简要地描述了这些构造函数,它首先使用顺序简要描述了程序清单16.1使用的7个构造函数,然后列出了C++11 新增的两个构造函数。使用构造函数时都进行了简化,即隐藏了这样一个事实:string 实际上是模板具体化 basic string的一个typedef,同时省略了与内存管理相关的参数(这将在本章后面和附录F中讨论)。sizetype是一个依赖于实现的整型,是在头文件string中定义的。string类将 string:mnpos 定义为字符串的最大长度,通常为 unsigned int 的最大值。另外,表格中使用缩写NBTS(null-terminated string)来表示以空字符结束的字符串–传统的C字符串。
// str1.cpp -- introducing the string class #include <iostream> #include <string> // using string constructors int main() { using namespace std; string one("Lottery Winner!"); // ctor #1 cout << one << endl; // overloaded << string two(20, '$'); // ctor #2 cout << two << endl; string three(one); // ctor #3 cout << three << endl; one += " Oops!"; // overloaded += cout << one << endl; two = "Sorry! That was "; three[0] = 'P'; string four; // ctor #4 four = two + three; // overloaded +, = cout << four << endl; char alls[] = "All's well that ends well"; string five(alls,20); // ctor #5 cout << five << "!\n"; string six(alls+6, alls + 10); // ctor #6 cout << six << ", "; string seven(&five[6], &five[10]); // ctor #6 again cout << seven << "...\n"; string eight(four, 7, 16); // ctor #7 cout << eight << " in motion!" << endl; // std::cin.get(); return 0; }
程序清单 16.1中程序还使用了重载+=运算符,它将一个字符串附加到另一个字符串的后面:重载的=运算符用于将一个字符串赋给另一个字符串;重载的<<运算符用于显示string对象;重载的[]运算符用于访问字符串中的各个字符。
下面是程序清单 16.1中程序的输出:
程序清单16.1中的程序首先演示了可以将string对象初始化为常规的C-风格字符串,然后使用重载的<<运算符来显示它:
string one("Lottery Winner!");
Cout <<one <<endl;
// ctor #1// overloaded <<
接下来的构造函数将 string 对象two初始化为由20个$字符组成的字符串:
string two(20,"');
// ctor #2
复制构造函数将string对象three 初始化为string对象one:
string three(one);
// ctor #3
重载的+=运算符将字符串“Oops!”附加到字符串one 的后面:
one += " Oops!";
// overloaded +=
这里是将一个C-风格字符串附加到一个 string 对象的后面。但+=运算符被多次重载,以便能够附加string 对象和单个字符:
one += two;//append a string object(not in program)
one += !!!://append a type char value(not in program)
同样,=运算符也被重载,以便可以将 string 对象、C-风格字符串或 char 值赋给 string 对象:
two="Sorry!That was";//assign a C-style string
two =onei
//assign astring object(not in program)
twO =?;
//assign achar value(not in program)
重载[1运算符(就像第12章的 String示例那样)使得可以使用数组表示法来访问 string 对象中的各个字符:
three[0]='P';
默认构造函数创建一个以后可对其进行赋值的空字符串:
//ctor #4
string four;
//overloaded +,=four =two +three;
第2行使用重载的+运算符创建了一个临时 string 对象,然后使用重载的=运算符将它赋给对象 four。正如所预料的,+运算符将其两个操作数组合成一个 sting对象。该运算符被多次重载,以便第二个操作数可以是 string 对象、C-风格字符串或 char 值。
第5个构造函数将一个C-风格字符串和一个整数作为参数,其中的整数参数表示要复制多少个字符:
char alls[]="All's well that ends well";
// ctor #5string five(alls,20);
从输出可知,这里只使用了前 20 个字符(“Al’s well that ends”)来初始化 five 对象。正如表 16.1指出的,如果字符数超过了C-风格字符串的长度,仍将复制请求数目的字符。所以在上面的例子中,如果用 40代替 20,将导致15个无用字符被复制到 five的结尾处(即构造函数将内存中位于字符串“Alls well that endswell”后面的内容作为字符)。
第6个构造函数有一个模板参数:
template<class Iter>string(Iter begin,Iter end);
begin 和 end 将像指针那样,指向内存中两个位置(通常,begin 和 end 可以是迭代器–广泛用于 STL中的广义化指针)。构造函数将使用 begin 和 end 指向的位置之间的值,对 string 对象进行初始化。[begin,end)来自数学中,意味着包括 begin,但不包括 end在内的区间。也就是说,end 指向被使用的最后一个值后面的一个位置。请看下面的语句:
string six(alls+6,alls +10);// ctor #6
由于数组名相当于指针,所以 alls+6和 alls +10的类型都是 char ,因此使用模板时,将用类型 char替换 Iter。第一个参数指向数组 alls 中的第一个 w,第二个参数指向第一个 wel 后面的空格。因此,six 将被初始化为字符串“well”。图16.1说明了该构造函数的工作原理。
现在假设要用这个构造函数将对象初始化为另一个string对象(假设为fve)的一部分内容,则下面的语句不管用:
string seven(five+6,five +10);
原因在于,对象名(不同于数组名)不会被看作是对象的地址,因此fve不是指针,所以five+6是没有意义的。然而,five[6]是一个char值,所以&five[6]是一个地址,因此可被用作该构造函数的一个参数。
string seven(&five[6],&five[10]);// ctor #6 again
第7个构造函数将一个 string 对象的部分内容复制到构造的对象中:
string eight(four,7,16);
// ctor #7
上述语句从four的第8个字符(位置7)开始,将16个字符复制到eight中。
构造函数 string(string&& str)类似于复制构造函数,导致新创建的 string为 str 的副本。但与复制构
造函数不同的是,它不保证将str视为const。这种构造函数被称为移动构造函数(move constructor)。在有些情况下,编译器可使用它而不是复制构造函数,以优化性能。第18章的“移动语义和右值引用”一节将讨论这个主题。
构造函数 string(initializer listil)让您能够将列表初始化语法用于string类。也就是说,它使得下面这样的声明是合法的:
string piano man=‘’,"i’,‘s’,‘2’‘t’);stringcomplang’L’,i’,‘s’,‘p’};
就 string类而言,这可能用处不大,因为使用C-风格字符串更容易,但确实实现了让列表初始化语法普遍实用的意图。本章后面将更深入地讨论模板initializer list。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。