C++中的vector容器对象学习笔记
C++中数组很坑,有没有类似Python中list的数据类型呢?类似的就是vector! vector 是同一种类型的对象的集合 ,每个对象都有一个对应的整数索引值。和 string 对象一样,标准库将负责管理与存储元素相关的内存。 我们把 vector 称为容器,是因为它可以包含其他对象 。 一个容器中的所有对象都必须是同一种类型的 。 vector对象的定义和初始化 同样的,使用前,导入头文件#include <vector> 可以使用using声明:using std::vector; vector 是一个类模板(class template)。使用模板可以编写一个类定义或函数定义,而用于多个不同的数据类型。因此,我们可以定义保存 string 对象的 vector,或保存 int 值的 vector,又或是保存自定义的类类型对象(如 Sales_items 对象)的 vector。 声明从类模板产生的某种类型的对象,需要提供附加信息,信息的种类取决于模板。 以 vector 为例,必须说明 vector 保存何种对象的类型,通过将类型放在类型放在类模板名称后面的尖括号中来指定类型:
【注意:1、若要创建非空的 vector 对象,必须给出初始化元素的值;2、当把一个 vector 对象复制到另一个 vector 对象时,新复制的 vector 中每一个元素都初始化为原 vectors 中相应元素的副本。但这两个 vector 对象必须保存同一种元素类型;3、可以用元素个数和元素值对 vector 对象进行初始化。构造函数用元素个数来决定 vector 对象保存元素的 个数,元素值指定每个元素的初始值】 vector对象动态增长 : vector 对象(以及其他标准库容器对象)的重要属性就在于 可以在运行时高效地添加元素。 【注意:因为 vector 增长的效率高 ,在元素值已知的情况下,最好是动态地添加元素。】 如果没有指定元素的初始化式,那么标准库将自行提供一个元素初始值进行,具体值为何,取决于存储在vector 中元素的数据类型。 如果为int型数据,那么标准库将用 0 值创建元素初始化式; 如果 vector 保存的是含有构造函数的类类型(如 string)的元素,标准库将用该类型的默认构造函数创建元素初始化式; 元素类型可能是没有定义任何构造函数的类类型。这种情况下,标准库仍产生一个带初始值的对象,这个对象的每个成员进行了值初始化。 #include <iostream> #include <string> #include <vector> int main() { std::vector<int> a; std::vector<int> b(a); std::vector<int> c(10,23); std::vector<std::string> svec(10,"null"); std::vector<std::string> svec2(10,"hi!"); std::vector<std::string> svec3(10); return 0; } 注意,没有=号! 和string类似! Returns true if v is empty; otherwise returns false如果 v 为空,则返回 true,否则返回 false。 .v.size() Returns number of elements in v返回 v 中元素的个数。 【注意:1、返回相应 vector 类定义的size_type 的值,和string类似。2、使用 size_type 类型时,必须指出该类型是在哪里定义的。vector 类型总是包括总是 包括 vector 的元素类型 vector<int>::size_type 】 v.push_back(t) Adds element with value t to end of v在 v 的末尾增加一个值为 t 的元素。以下为例子: #include <iostream> #include <string> #include <cctype> #include <vector> int main() { // read words from the standard input and store them as elements in a vector std::string word; std::vector<std::string> text; // empty vector while (std::cin >> word) { text.push_back(word); // append word to text for(std::vector<int>::size_type ix =0; ix != text.size(); ++ix) std::cout<<"Now text["<<ix<< "]is: "<<text[ix]<<std::endl; } return 0; } 结果为: Hello Now text[0]is: Hello world! Now text[0]is: Hello Now text[1]is: world!
2、下标操作可以改变已有元素:例如上例,可以在最后加上:text[0] = "elements"; 3、当然和list一样,肯定不能text[100] = "elements";在Python中这样操作list回报下标越界, C++中编译不会报错,运行自动退出!【 数组操作时这个会坑死你,不会报错,不会退出!理所当然,缓冲区溢出了,黑客们太喜欢了! 】 4、由于动态增长, 不能先测试长度 ,而是循环中动态测试!否则会出现莫名其妙的BUG!有人会担心效率?别担心!代价很小【内联函数】。 v[n] Returns element at position n in v返回 v 中位置为 n 的元素。 (1)v1 = v2[/code] Replaces elements in v1 by a copy of elements in v2把 v1 的元素替换为 v2 中元素的副本。 (2)v1 == v2[/code] Returns true if v1 and v2 are equal如果 v1 与 v2 相等,则返回 true。 (3)!=,<,<=,>,and >= Have their normal meanings保持这些操作符惯有的含义。 一个简单的例子 读入一段文本到 vector 对象,每个单词存储为 vector 中的一个元素。把vector 对象中每个单词转化为大写字母。输出 vector 对象中转化后的元素,每八个单词为一行输出。 假设文本为:in the vector. transform each word into uppercase letters. Print the transformed elements from the vector,printing eight words to a line. #include <iostream> #include <string> #include <vector> std::string deal_word(std::string word) { std::string WORD; // 创建空字符串 for(std::string::size_type ix =0; ix != word.size(); ++ix) { if (not ispunct(word[ix])) { WORD += toupper(word[ix]); //连接非标点字符到字符串 } } return WORD; } int main() { std::string word; // 缓存输入的单词 std::vector<std::string> text; // empty vector std::cout<<"Please input the text:"<<std::endl; //提示输入 while (std::cin >> word and word != "INPUTOVER") // INPUTOVER 用于标示输入结束,也可以ctrl + z停止输入 { word = deal_word(word); // 单词处理 text.push_back(word); // append word to text } for(std::vector<int>::size_type ix =0,j = 0; ix != text.size(); ++ix,++j) { if (j==8) // 8个单词一行 { std::cout<<std::endl; //换行 j = 0; //重新计数 } std::cout<<text[ix]<<" "; //加空格! } return 0; } 结果为: Please input the text: in the vector. transform each word into uppercase letters. Print the transformed elements from the vector,printing eight words to a line. INPUTOVER IN THE VECTOR TRANSFORM EACH WORD INTO UPPERCASE LETTERS PRINT THE TRANSFORMED ELEMENTS FROM THE VECTOR PRINTING EIGHT WORDS TO A LINE vector.resize 与 vector.reserve reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。 vector<int> myVec; myVec.reserve( 100 ); // 新元素还没有构造,// 此时不能用[]访问元素 for (int i = 0; i < 100; i++ ) ...{ myVec.push_back( i ); //新元素这时才构造 } myVec.resize( 102 ); // 用元素的默认构造函数构造了两个新的元素 myVec[100] = 1; //直接操作新元素 myVec[101] = 2; 初次接触这两个接口也许会混淆,其实接口的命名就是对功能的绝佳描述,resize就是重新分配大小,reserve就是预留一定的空间。这两个接口即存在差别,也有共同点。下面就它们的细节进行分析。 void resize(size_type new_size) { resize(new_size,T()); } void resize(size_type new_size,const T& x) { if (new_size < size()) erase(begin() + new_size,end()); // erase区间范围以外的数据,确保区间以外的数据无效 else insert(end(),new_size - size(),x); // 填补区间范围内空缺的数据,确保区间内的数据有效 } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |