一、命名空间的using指示与using声明
1、using声明
(1)一个using声明一次只引入一个命名空间成员。
(2)using声明的作用域为:从using声明点开始,直到包含该using声明的作用域的末尾,名字都是可见的。类作用域中的using声明局限于被定义类的基类中定义的名字。
using std::string;
using std::vector;
2、using指示(待续)
(1)using指示使得特定命名空间的所有名字可见,没有限制。
(2)可以尝试使用using指示编写程序,但在使用多个库的时候,这样做会重新引入名字冲突的所有问题。因此,使用using指示应有所限制。
3、除了在函数或其他作用域内部,头文件不应该包含using声明或using指示。在顶级作用域包含using指示或using声明的头文件,具有将该名字注入所有包含该头文件的文件中的效果。在头文件中,最好总是使用完全限定的标准库名字,比如 std::cout 等。
注:头文件中应该只定义确实必要的东西。
二、标准库string类型
1、string对象的定义和初始化
(1)string标准库的默认构造函数将string对象初始化为空串。
(2)编程时要注意区分字符串字面值和string数据类型的使用。
2、string对象的读写
(1)可以用iostream和string标准库,使用标准输入输出操作符来读写string对象。
cin操作符会读取并忽略开头所有的空白字符(空格、换行、制表符等);并读取字符直至再次遇到空白字符,读取终止。
int main()
{
string result_str, str;
cout << "Enter strings(Ctrl + z to end):" << endl;
while(cin >> str)
result_str = result_str + str;
return 0;
}
(2)用getline读取整行文本
此函数接受两个参数:一个输入流对象和一个string对象。将读取的内容保存到string对象,但不包括换行符。getline不忽略开头的换行符,即便它是输入的第一个字符,geline也将停止读入并返回。
int main()
{
string line;
while(getline(cin, line))
cout << line << endl;
return 0;
}
3、string对象的操作
(1)string::size_type类型
这是string类类型的配套类型,通过这些类型,库类型的使用就与机器无关。存储string的size操作结果的变量必须为string::size_type类型。注意,不要把size的返回结果赋给一个int变量。
string对象支持下标操作,string对象的索引变量最好也用string::size_type类型。
(2)string对象与字符串字面值的连接
当进行string对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是string类型的。
string s1 = "hello";
string s2 = s1 + ", " + "world"; //OK
string s3 = "hello" + ", " + "world"; //Error
对于s2和s3,依次来看每个子表达式。子表达式s1 + ", "将返回一个新string对象。
三、标准库vector类型
vector不是一种数据类型,而只是一个类模板。vector<int>和vector<string>都是数据类型。
1、vector的定义和初始化
(1)vector对象(以及其他标准库容器对象)的重要属性就在于可以在运行时高效的添加元素。因此,虽然可以对给定元素个数的vector对象预先分配内存,但更有效的方法是先初始化一个空vector对象,然后再动态地增加元素。
(2)若没有指定vector中元素的初始化式,则标准库将自行提供一个元素初始化值进行值初始化。此值依赖于元素的数据类型。
2、vector对象的操作
(1)vector对象的下标操作。vector对象支持下标操作。但应注意:下标仅能用于获取已经存在的元素,且通过下标操作进行赋值时,不会添加任何元素。
(2)关于vector的for循环常常写成如下形式:
for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
ivec[ix] = 0;
应注意两点:
第一,优先选用 != 而不是 < 来编写循环判断条件(但当循环变量的步长大于1时,则应使用< 。否则可能出现无限循环的情况)。
第二,调用size成员函数而不提前保存它返回的值,这是一个良好的编程习惯。这是因为,C++中有些数据结构(比如vector)可以动态增长,循环可以很容易的增加新的元素。这样的运行代价其实很小,因为像size这样的小库函数几乎都定义为内联函数。
(3)不能用cout输出操作符直接输出vector对象。
四、标准库bitset类型
1、bitset对象的定义和初始化
(1)与vector类似,bitset类也是类模板。不同bitset对象的区别在于长度而不是类别。定义bitset时,需明确指出bitset含有多少位,且给出的长度必须是常量表达式。
(2)用string对象初始化bitset对象。string对象与bitset对象之间是反向转化的。string对象最右边字符(下标最大)用来初始化bitset对象的低阶位(下标为0)。
2、bitset对象的操作
(1)bitset对象支持下标操作。但是,bitset对象的下标编号从右向左,最右边编号为0;而string对象的下标编号从左向右,最左边编号为0。
(2)可用cout输出操作符输出bitset对象中的位模式。
五、迭代器简介
1、容器的iterator类型
(1)迭代器是一种检查容器内元素并遍历元素的数据类型。
(2)标准库为每一种标准容器(包括vector)定义了相应的iterator类型,而这种类型支持(概念上的)迭代器的各种操作。但是只有少数的容器支持下标操作。
2、begin和end操作
vector<int>::iterator iter = ivec.begin();
iter指向元素ivec[0],类似一个指针。
由end操作返回的迭代器指向vector的“末端元素的下一个”,指向了一个不存在的元素。
3、自增和解引用运算
(1)解引用运算符:*。*iter = 0;
(2)迭代器的自增,是把容器中的迭代器“向前移动一个位置”。
(3)不能对end操作返回的迭代器进行解引用或自增运算。
4、const_iterator与const迭代器
(1)使用const_iterator类型时,我们可以得到一个迭代器,它自身的值可以改变,但不能用来改变其所指向的元素的值。可以对迭代器进行自增以及使用解引用操作符来读取值,但不能对该元素赋值。若只需遍历容器中的元素而无需修改他们,则可以使用const_iterator。
(2)const_iterator既可以用于const vector或非const vector。
(3)const迭代器是迭代器常量,该迭代器本身的值不能修改,即该迭代器在定义时需要初始化,而且初始化之后,就不能再指向其他元素。const迭代器几乎没有用。
vector<int> nums(10);
const vector<int>::iterator cit = nums.begin();
*cit = 1; //OK
++cit; //error
5、迭代器的算术操作
有两种:
第一,iter + n;n的类型应为vector的size_type类型或difference_type类型。
第二,iter1 - iter2;结果为difference_type的signed类型的值。iter1和iter2都必须指向同一vector中的元素。
没有定义两个迭代器相加的操作:iter1 + iter2(非法)。
注意:任何改变vector长度的操作都会使已存在的迭代器失效!!比如push_back之后。