3.3.2 向vector对象中添加元素
对vector对象来说,直接初始化的方式适用于三种情况:初始值已知且数量较少、初始值是另一个vector对象的副本、所有元素的初始值都一样。然而更常见的情况是:创建一个vector对象时并不清楚实际所需的元素个数,元素的值也经常无法确定。还有些时候即使元素的初值已知,但如果这些值总量较大而各不相同,那么在创建vector对象的时候执行初始化操作也会显得过于烦琐。
举个例子,如果想创建一个vector对象令其包含从0到9共10个元素,使用列表初始化的方法很容易做到这一点;但如果vector对象包含的元素是从0到99或者从0到999呢?这时通过列表初始化把所有元素都一一罗列出来就不太合适了。对于此例来说,更好的处理方法是先创建一个空vector,然后在运行时再利用vector的成员函数push_back向其中添加元素。push_back负责把一个值当成vector对象的尾元素"压到(push)"vector对象的"尾端(back)"。例如:
- vector<int> v2; // 空vector对象
- for (int i = 0; i != 100; ++i)
- v2.push_back(i); // 依次把整数值放到v2尾端
- // 循环结束后v2有100个元素,值从0到99
在上例中,尽管知道vector对象最后会包含100个元素,但在一开始还是把它声明成空vector,在每次迭代时才顺序地把下一个整数作为v2的新元素添加给它。
同样的,如果直到运行时才能知道vector对象中元素的确切个数,也应该使用刚刚这种方法创建vector对象并为其赋值。例如,有时需要实时读入数据然后将其赋予vector对象:
- // 从标准输入中读取单词,将其作为vector对象的元素存储
- string word;
- vector<string> text; // 空vector对象
- while (cin >> word) {
- text.push_back(word); // 把 word添加到text后面
- }
和之前的例子一样,本例也是先创建一个空vector,之后依次读入未知数量的值并保存到text中。
关键概念:vector对象能高效增长
C++(www.cppentry.com)标准要求vector应该能在运行时高效快速地添加元素。因此既然vector对象能高效地增长,那么在定义vector对象的时候设定其大小也就没什么必要了,事实上如果这么做性能可能更差。只有一种例外情况,就是所有(all)元素的值都一样。一旦元素的值有所不同,更有效的办法是先定义一个空的vector对象,再在运行时向其中添加具体值。此外,9.4节(第355页)将介绍,vector还提供了方法,允许我们进一步提升动态添加元素的性能。
开始的时候创建空的vector对象,在运行时再动态添加元素,这一做法与C语言及其他大多数语言中内置数组类型的用法不同。特别是如果用惯了C或者Java,可以预计在创建vector对象时顺便指定其容量是最好的。然而事实上,通常的情况是恰恰相反。
向vector对象添加元素蕴含的编程(www.cppentry.com)假定
由于能高效便捷地向vector对象中添加元素,很多编程(www.cppentry.com)工作被极大简化了。然而,这种简便性也伴随着一些对编写程序更高的要求:其中一条就是必须要确保所写的循环正确无误,特别是在循环有可能改变vector对象容量的时候。
随着对vector的更多使用,我们还会逐渐了解到其他一些隐含的要求,其中一条是现在就要指出的:如果循环体内部包含有向vector对象添加元素的语句,则不能使用范围for循环,具体原因将在5.4.3节(第188页)详细解释。
范围for语句体内不应改变其所遍历序列的大小。
3.3.2节练习
练习3.14:编写一段程序,用cin读入一组整数并把它们存入一个vector对象。
练习3.15:改写上题的程序,不过这次读入的是字符串。