9.9 begin 和 cbegin 两个函数有什么不同?
答:(1) cbegin() 是C++新标准引入的,用以支持auto与begin()和end()函数使用的。它返回的是容器第一个元素的const迭代器,只能够以只读形式访问容器元素,不能够通过它修改元素内容。当不需要写访问时,应该使用cbegin(). (2)begin()是被重载过的,也就是说实际上是有两个begin成员,一个是const类型的成员,返回的是是const_iterator类型;另一个是非常量类型,返回的实际 iterator, 可以对容器类型进行修改。
9.10 下面四个对象分别是什么类型?
vector<int> v1;
const vecto<int> v2;
auto it1 = v1.begin();
auto it2 = v2.begin();
auto it3 = v1.cbegin();
auto it4 = v2.cbegin();
答: v1 是 int的vector类型,可以修改v1的内容, v2 是 int的常量vector类型,不可以修改v2的内容。it1是普通非常量迭代器,it2 是常量迭代器。it3和it4都是常量迭代器。
9.11 对6种创建和初始化vector对象的方法,每一种都给出一个实例,解释每个vector包含什么值?
答:vector<int> i = {0, 1, 2}; // 列表初始化
vector<int> ivec{0, 1, 2}; // 列表初始化
vector<int> ivec; // ivec 为空
vector<int> ivec(i); // ivec初始化拷贝 i,其中元素与i 相等
vector<int> ivec = i; // 与上一句相同
vector<int> ivec(i.begin(), i.end()); // ivec包含i的首元素与尾元素之间的元素
vector<int> ivec(10); // ivec包含10个元素,每个元素都初始化为0
vector<int> ivec(10, 2); // ivec包含10个元素,每个元素都初始化为2
>
9.12 对于接受一个容器创建其拷贝的构造函数,和接受两个迭代器创建拷贝的构造函数,解释他们的不同?
答:接受一个已有容器的构造函数会拷贝该容器的所有元素,即是该容器的完整拷贝。当我们需要对一个容器进行完整的拷贝时,这种初始化是非常方便的。创建容器的拷贝时,两个容器的类型必须相同,且其所存储元素的类型也必须相同。当不需要已有容器的全部元素时,可以使用接受两个迭代器创建拷贝的构造函数,选择自己需要元素子集。因为该方法是从迭代器中读取相应的元素,所以两个容器的类型不需要相同,只需保证容器中的元素类型相同,或者可以转化为初始化容器中的元素类型即可。9.13 如何从一个list初始化一个vector?从vector又该如何创建?编写代码验证你的答案
答:从其他类型容器初始化另一个类型的容器,只有使用迭代器范围初始化这一方式。虽然vector与vector的容器类型相同,但是其元素类型不同,所以不能够使用容器直接初始化。#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
{
list<int> ilist = { 0, 1, 2 }; // 初始化 ilist
auto begin = ilist.cbegin(); // 首元素迭代器
auto end = ilist.cend(); // 尾元素之后的迭代器
vector<double> dvec(begin, end); // 使用迭代器初始化 dvec
for (auto i : dvec)
{
cout << i << endl;
}
}
{
vector<int> ivec = { 0, 1, 2 };
auto begin = ivec.cbegin();
auto end = ivec.cend();
//vector<double> dvec(ivec); // 此处会报错提示,元素类型不同
vector<double> dvec(begin, end);
for (auto i : dvec)
{
cout << i << endl;
}
}
return 0;
}
** 9.14 编写程序,将一个list中的 char* 指针(指向c风格字符串)元素赋值给一个vector中的string**
答:因为涉及到不同容器之间的赋值,所以需要使用迭代其,即使用assign(b, e)进行赋值操作。#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
list<const char*> clist = { "A", "B", "C" };
vector<string> svec;
auto begin = clist.cbegin();
auto end = clist.cend();
svec.assign(begin, end);
for (auto i : svec)
{
cout << i << endl;
}
return 0;
}
** 9.15 编写程序,判断两个 vector< int > 是否相等**
答:#include <iostream>
#include <list>
#include <vector>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> ivec1{ 1, 2, 3 };
vector<int> ivec2{ 1, 2, 3, 4 };
bool flag = (ivec1 == ivec2);
cout << boolalpha;
cout << flag << endl;
return 0;
}
** 9.16 重写上一题程序,比较一个 list< int>中的元素和一个 vector< int> 中的元素。**
答:该题有两种思路。第一种是对读取容器中的元素进行比较,因为容器类型不同,所以无法直接应用关系运算符。第二种思路是将list中的元素内容直接拷贝到新建的vector中,然后直接使用关系运算符进行比较,比较方便,但是创建新的容器会额外占用内存,并且拷贝数据需要额外时间。(但是实际测出来的效果,第二种时间比较少,大家可以试一试)#include <iostream>
#include <list>
#include <vector>
#include <string>
#include<Windows.h>
using namespace std;
bool list_vec_equal(list<int>, vector<int>);
int main(int argc, char* argv[])
{
list<int> ilist{ 1, 2, 3, 4, 5, 6, 7 ,8 ,9 ,10 };
vector<int> ivec{ 1, 2, 3, 4, 5, 6, 7 ,8 ,9 ,10, 11 };
double sum1 = 0, sum2 = 0;
{
for (int i = 0; i < 10000; i++)
{
DWORD64 start, finish;
double time;
start = GetTickCount64();
bool flag = list_vec_equal(ilist, ivec);
finish = GetTickCount64();
time = finish - start;
sum1 = sum1 + time;
cout << boolalpha;
cout << flag << "运行时间 " << time << " ms" << endl;
}
}
{
for (int j = 0; j < 10000; j++)
{
DWORD64 start, finish;
double time;
start = GetTickCount64();
vector<int> ivec2(ilist.cbegin(), ilist.cend());
bool flag = (ivec == ivec2);
finish = GetTickCount64();
time = finish - start;
sum2 = sum2 + time;
cout << boolalpha;
cout << flag << "运行时间 " << time << " ms" << endl;
}
}
cout << sum1 << " " << sum2 << " ms" << endl;
return 0;
}
bool list_vec_equal(list<int> ilist, vector<int> ivec)
{
auto begin1 = ilist.cbegin();
auto end1 = ilist.cend();
auto begin2 = ivec.cbegin();
if (ilist.size() != ivec.size())
{
cout << false << endl;
return false;
}
for (; begin1 != end1; begin1++, begin2++)
{
if (*begin1 != *begin2)
return false;
}
return true;
}
** 9.17 假定 c1 和 c2 是两个容器,下面的比较操作有和限制,如果有的话?**
if (c1 < c2)
答:首先,c1与c2必须是相同类型的容器,且元素类型相同。其次,元素类型需支持 “<” 关系运算符。