C++ 入门笔记2--标准库类型
1.命名空间的 using 声明
a.使用 using 声明可以在不需要加前缀 namespace_name:: 的情况下访问命名空间中的名字。using 声明的形式如下:
using namespace::nameb.一个 using 声明一次只能作用于一个命名空间成员。using 声明可用来明确指定在程序中用到的命名空间中的名字,如果希望使用 std(或其他的命名空间)中的几个名字,则必须为要用到的每个名字都提供一个 using 声明
c.有一种情况下,必须总是使用完全限定的标准库名字:在头文件中。理由是头文件的内容会被预处理器复制到程序中。用 #include 包含文件时,相当于头文件中的文本将成为我们编写的文件的一部分。如果在头文件中放置 using 声明,就相当于在包含该头文件 using 的每个程序中都放置了同一 using,不论该程序是否需要 using 声明。
2.标准库 string 类型
a. string 对象的定义和初始化
string s1;默认构造函数 s1 为空串
string s2(s1);将 s2 初始化为 s1 的一个副本
string s3("value");将 s3 初始化为一个字符串字面值副本
string s4(n, 'c');将 s4 初始化为字符 'c' 的 n 个副本
b.因为历史原因以及为了与 C 语言兼容,字符串字面值与标准库 string 类型不是同一种类型。这一点很容易引起混乱,编程时一定要注意区分字符串字面值和 string 数据类型的使用,这很重要。
c.s.size()操作返回的是 string::size_type 类型的值。
d.当进行 string 对象和字符串字面值混合连接操作时,+ 操作符的左右操作数必须至少有一个是 string 类型的:
string s1 = "hello"; // no punctuation string s2 = "world"; string s5 = s1 + ", " + "world"; // ok: each + has string operand string s6 = "hello" + ", " + s2; // error: can't add string literalse.string 类型通过下标操作符([ ])来访问 string 对象中的单个字符。下标操作符需要取一个 size_type 类型的值,来标明要访问字符的位置。这个下标中的值通常被称为“下标”或“索引”.下标操作可用作左值.虽然任何整型数值都可作为索引,但索引的实际数据类型却是类型 unsigned 类型 string::size_type。
3.标准库 vector 类型a.vector 是同一种类型的对象的集合,每个对象都有一个对应的整数索引值。和 string 对象一样,标准库将负责管理与存储元素相关的内存。我们把 vector 称为容器,是因为它可以包含其他对象。一个容器中的所有对象都必须是同一种类型的。b.vector 不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。vector 类型的每一种都指定了其保存元素的类型。因此,vector<int> 和 vector<string> 都是数据类型。c.声明从类模板产生的某种类型的对象,需要提供附加信息,信息的种类取决于模板。以 vector 为例,必须说明 vector 保存何 种对象的类型,通过将类型放在类型放在类模板名称后面的尖括号中来指定类型:vectorivec; // ivec holds objects of type int vector Sales_vec; // holds Sales_items d.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 个副本。
e.值初始化:如果没有指定元素的初始化式,那么标准库将自行提供一个元素初始值进行值初始化(value initializationd)。这个由库生成的初始值将用来初始化容器中的每个元素,具体值为何,取决于存储在 vector 中元素的数据类型。 如果一些有自定义构造函数但没有默认构造函数的类,在初始化这种类型的 vector 对象时,程序员就不能仅提供元素个数,还需要提供元素初始值。
如果 vector 保存内置类型(如 int 类型)的元素,那么标准库将用 0 值创建元素初始化式:
vectorfvec(10); // 10 elements, each initialized to 0 如果 vector 保存的是含有构造函数的类类型(如 string)的元素,标准库将用该类型的默认构造函数创建元素初始化式:
vectorsvec(10); // 10 elements, each an empty string 还有第三种可能性:元素类型可能是没有定义任何构造函数的类类型。这种情况下,标准库仍产生一个带初始值的对象,这个对象的每个成员进行了值初始化。f.成员函数 size 返回相应 vector 类定义的 size_type 的值。使用 size_type 类型时,必须指出该类型是在哪里定义的。vector 类型总是包括总是包括 vector 的元素类型:
vector::size_type // ok vector::size_type // error g.警告:仅能对确知已存在的元素进行下标操作.不幸的是,试图对不存在的元素进行下标操作是程序设计过程中经常会犯的严重错误。所谓的“缓冲区溢出”错误就是对不存在的元素进行下标操作的结果。这样的缺陷往往导致 PC 机和其他应用中最常见的安全问题。
4.迭代器简介
a.迭代器是一种检查容器内元素并遍历元素的数据类型。每种容器类型都定义了自己的迭代器类型,如 vector:
vector::iterator iter; b.每种容器都定义了一对命名为 begin 和 end 的函数,用于返回迭代器。如果容器中有元素的话,由 begin 返回的迭代器指向第一个元素:vector::iterator iter = ivec.begin(); c.由 end 操作返回的迭代器指向 vector 的“末端元素的下一个”。由 end 操作返回的迭代器并不指向 vector 中任何实际的元素,相反,它只是起一个哨兵(sentinel)的作用,表示我们已处理完 vector 中所有元素。d.迭代器类型定义了一些操作来获取迭代器所指向的元素,并允许程序员将迭代器从一个元素移动到另一个元素。
迭代器类型可使用解引用操作符(dereference operator)(*)来访问迭代器所指向的元素:
*iter = 0;e.const_iterator 类型:使用 const_iterator 类型时,我们可以得到一个迭代器,它自身的值可以改变,但不能用来改变其所指向的元素的值。可以对迭代器进行自增以及使用解引用操作符来读取值,但不能对该元素赋值。注意下两者的区别:
vector::const_iterator // an iterator that cannot write elements const vector ::iterator // an iterator whose value cannot change f.迭代器算术操作:可以用迭代器算术操作来移动迭代器直接指向某个元素,例如,下面语句直接定位于 vector 中间元素:
g.任何改变 vector 长度的操作都会使已存在的迭代器失效。例如,在调用 push_back 之后,就不能再信赖指向 vector 的迭代器的值了。vector::iterator mid = vi.begin() + vi.size() / 2;
5.标准库 bitset
初始化bitset对象:
bitset<n> b;b 有 n 位,每位都 0
bitset<n> b(u);b 是 unsigned long 型 u 的一个副本
bitset<n> b(s);b 是 string 对象 s 中含有的位串的副本
bitset<n> b(s, pos, n);b 是 s 中从位置 pos 开始的&nbps;n 个位的副本
bitset对象的操作:
b.any() b 中是否存在置为 1 的二进制位?
b.none() Are no bits in b on?
b.count() b 中不存在置为 1 的二进制位吗?
b.size() b 中置为 1 的二进制位的个数
b[pos] 访问 b 中在 pos 处二进制位
b.test(pos) b 中在 pos 处的二进制位置为 1
b.set() 把 b 中所有二进制位都置为 1
b.set(pos) 把 b 中在 pos 处的二进制位置为 1
b.reset() 把 b 中所有二进制位都置为 0
b.reset(pos) 把 b 中在 pos 处的二进制位置为 0
b.flip() 把 b 中所有二进制位逐位取反
b.flip(pos) 把 b 中在 pos 处的二进制位取反
b.to_ulong() 用 b 中同样的二进制位返回一个 unsigned long 值
os << b 把 b 中的位集输出到 os 流
a.有些程序要处理二进制位的有序集,每个位可能包含 0(关)1(开)值。标准库提供的 bitset 类简化了位集的处理。
b.与 vector 不一样的是 bitset 类型对象的区别仅在其长度而不在其类型。在定义 bitset 时,要明确 bitset 含有多少位,须在尖括号内给出它的长度值.
c.初始化 bitset 对象的方法:给出的长度值必须是常量表达式。正如这里给出的,长度值值必须定义为整型字面值常量或是已用常量值初始化的整型的 const 对象。
bitset<32> bitvec; // 32 bits, all zero
d.和 vector 的元素一样,bitset 中的位是没有命名的,程序员只能按位置来访问。位集合的位置编号从 0 开始,因此,bitvec 的位序是从 0 到 31。以 0 位开始的位串是低阶位(low-order),以 31 位结束的位串是高阶位(high-order)。
e.当用 unsigned long 值作为 bitset 对象的初始值时,该值将转化为二进制的位模式。而 bitset 对象中的位集作为这种位模式的副本。如果 bitset 类型长度大于 unsigned long 值的二进制位数,则其余的高阶位将置为 0;如果 bitset 类型长度小于 unsigned long 值的二进制位数,则只使用 unsigned 值中的低阶位,超过 bistset 类型长度的高阶位将被丢弃。
f.用 string 对象初始化 bitset 对象:
当用 string 对象初始化 bitset 对象时,string 对象直接表示为位模式。从 string 对象读入位集的顺序是从右向左(from right to left): 相当于把str中的数据取出,右端对齐,放在bitset里面
string strval("1100"); bitset<32> bitvec4(strval);