练习13.41
在push_back中我们为什么在construct调用后置递增
::因为first_free指针就是第一个空闲位置,使用前置每次插入都会隔一个位置
练习13.42
在你的textQuery和Queryresult类中用strvec代替vector<string>进行测试
::用StrVec替换vector<string>测试即可
练习13.43
重写free成员,用for_each和lambda来代替for循环destroy元素,你倾向于哪个?
::倾向于for_each,更好看
inline
void StrVec::free()
{
if (elements) {
for_each (elements,first_free,alloc.destroy )
alloc.deallocate(elements, cap - elements);
}
}
练习13.44
编写标准库string类的简化版本,命名为String。你的类应该至少有一个默认构造函数和一个接受c风格的字符串指针参数的构造函数,使用allocator为你的String类分配所需内存
#include <memory>
#include <memory>
using namespace std;
class String{
public:
String():elements(nullptr),first_free(nullptr),cap(nullptr){ }
String(const String& s){
auto data=alloc_ncopy(s.begin(),s.end());
elements=data.first;
first_free=cap=data.second;
}
String& operator=(const String&s){
auto data=alloc_ncopy(s.begin(),s.end());
free();
elements=data.first;
first_free=cap=data.second;}
~String(){free();}
String(const char*a,const char*b)
{
auto data=alloc_ncopy(a,b);
elements=data.first;
first_free=cap=data.second;
}
void push_back(char&c){check();alloc.construct(first_free++,c); }
size_t size()const{return first_free-elements;}
size_t capacity(){return cap-elements; }
char* begin()const{return elements; }
char* end()const{return first_free; }
private:
static allocator<char> alloc;
char* elements;
char* first_free;
char* cap;
void check(){if(size()==capacity())reallocate();}
pair<char*,char*> alloc_ncopy(const char*a,const char*b){
auto data=alloc.allocate(b-a);
return {data,uninitialized_copy(a,b,data)};
}
void reallocate()
{
size_t newcapacity = size() ? 2 * size() : 1;
char* newdata =alloc.allocate(newcapacity);
char*dest=newdata;
char*elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, *elem++);
free();
elements=newdata;
first_free = dest;
cap = elements + newcapacity;
}
void free()
{
if (elements) {
for (char*p = first_free; p != elements; )
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
};
allocator<char> String::alloc;
练习13.45
解释右值引用和左值引用的区别
::可以这样理解右值是值,左值是地址,所以分别是对值的引用和对地址的引用,不过右值引用和左值引用都是左值
练习13.46
什么类型的引用可以绑定到下面的初始化器上?
int f();
vector<int> vi(100);
int&& r1=f();
int& r2=vi[0];
int& r3=r1;
int&& r4=vi[0]*f();
练习13.47
对你在练习13.44中定义的String类,为它的拷贝构造函数和拷贝赋值运算符添加一条语句,打印一条信息
String(const String& s){
auto data=alloc_ncopy(s.begin(),s.end());
elements=data.first;
first_free=cap=data.second;
cout<<"拷贝构造"<<endl;
}
String& operator=(const String&s){
auto data=alloc_ncopy(s.begin(),s.end());
free();
elements=data.first;
first_free=cap=data.second;
cout<<"赋值运算"<<endl;}
练习13.48
定义一个vector<String>并在其上多次调用push_back,观察拷贝构造调用次数。
::每当vector内存满了要push_back,就会重新分配等于自身两倍的内存,并将已有的元素拷贝过去。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/280893.html