2013.05.14_C++primer笔记
1 为什么头文件只能用于声明,不能用于定义?
在说明这个问题之前,有三个例外是可以定义在头文件中的:类,值在编译时就已知道的const对象和inline函数。 在头文件中定义这些实体,是因为编译器需要它们的定义来产生代码。现在来看看这个问题。
首先明确的是,如果把定义写在.h文件中,那么很可能出现多重定义的报错。
每一个点CPP文件都是单独编译的,该点CPP文件中用到的类型必须在它所include 的头文件当中找到,相当于把它所有include的文件中的代码都加到该CPP文件的前面,但是声明的部分将不会出现在编译后的点O文件。这样的结果就是,当有多个文件包含相同的头文件时,并且在该头文件中有定义,那么在多个文件中都会出现相同的定义,而不是声明。所以最后的结果还是多重定义的bug。
2 标准库vector类型
vector是同一种类型的对象的集合。vector不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。
vector<T> v1; | vector保存类型为T的对象。默认构造函数v1为空。 |
vector<T> v2(v1); | v2是v1的一个副本。 |
vector<T> v3(n, i); | v3包含n个值为i的元素。 |
vector<T> v4(n); | v4含有值初始化的元素的n个副本。 |
v.push_back(t):向vector中添加元素到vector的末尾。
v.size():返回vector中的元素个数,其类型为vector<int>::size_type。该类型必须指出是在哪里定义的,即尖括号中必须指明vector的元素类型。
for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
ivec[ix] = 0;
在此例中,有一个安全的泛型编程的概念。
必须是已存在的元素才能用下表操作符进行索引。
例: 定义vector对象,给定10个元素,每个元素值为42.
1 vector<int> ivec(10, 42);
2 vector<int> ivec;
for (cnt = 1; cnt <= 10; ++cnt)
ivec.push_back(42);
3 vector<int> ivec;
vector<int>::iterator iter = ivec.end();
for (int i = 0; i != 10; ++i) {
ivec.insert(iter, 42);
ivec = ivec.end();
}
3 迭代器
迭代器是一种检查容器内元素并遍历元素的数据类型。
vector<int> :: iterator iter = ivec.begin();
由begin返回的迭代器指向第一个元素。
由end返回的迭代器指向vector的“末端元素的下一个”,通常成为超出末端迭代器。它并不指向vector中的任何实际元素,只是起到一个哨兵的作用,表明我们已经处理完vector中的所有元素。
如果vector为空,则begin返回的迭代器与end返回的迭代器相同。
解引用操作符:* ,访问迭代器所指向的元素。
使用迭代器编写循环
const_iterator:如果我们对const_iterator类型解引用时,则可以得到一个指向const对象的引用,如同任何常量一样,该对象不能进行重写。但是它自身的值可以改变。for(vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
*iter = 0;
任何改变vector长度操作都会使已存在打得迭代器失效。例如在调用push_back之后,就不能再信赖指向vector的迭代器的值了。
4 标准库bitset类型
5 小结
string类型提供了变长的字符串,而vector类型则可用于管理同一类型的对象集合。