出现的问题:书中alloc为static,编译时连接错误,不使用static可正常运行。因为在c++11中,static必须要初始化
//现有知识储备不知道怎么给alloc初始化,所以……暂时去掉static
StrVec.h头文件内容为
#pragma once
#ifndef STRVEC_H
#define STRVEC_H
#include<string>
#include<memory>
#include<utility>//move
#include<initializer_list>
using std::string;
using std::pair;
using std::allocator;
using std::initializer_list;
//成员elements, first_free,cap----工具函数:alloc_n_copy, free, chk_n_alloc, reallocate
class StrVec {
public:
StrVec() :elements(nullptr), first_free(nullptr), cap(nullptr) {}//默认构造函数
StrVec(initializer_list<string> v1);
StrVec(const StrVec&);//拷贝构造函数
StrVec::StrVec(StrVec &&s) noexcept:elements(s.elements), first_free(s.first_free), cap(s.cap)
{ s.elements = s.cap = s.first_free = nullptr; }//移动构造函数
StrVec& operator = (const StrVec&);//拷贝赋值运算符
StrVec& operator = (StrVec &&s);//移动赋值运算符
~StrVec() { free(); }//析构
void push_back(const string&);
size_t size() { return first_free - elements; }
size_t capacity() { return cap - elements; }
string* begin() const { return elements; }
string* end() const { return first_free; }
size_t capacity() const { return cap - elements; }
void reserve(size_t);
void resize(size_t n);
void resize(size_t n, const string &s);
private:
allocator<string> alloc;//alloc用来分配内存
pair<string*, string*> alloc_n_copy(const string*, const string*);
void chk_n_alloc() { if (size() == capacity()) reallocate(); }
void free();
void reallocate();
void reallocate(size_t);
string *elements;
string *first_free;
string *cap;
};
void StrVec::push_back(const string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
}
pair<string*, string*> StrVec::alloc_n_copy(const string *b, const string *e)
{
auto data = alloc.allocate(e - b);
return{ data, uninitialized_copy(b, e, data) };
}
void StrVec::free()
{
//用lambda表达式的版本
// for_each(elements, first_free, [](string &s) {alloc.destroy(&s); });//此语句要求alloc为static类型
if (elements) {
for (auto p = first_free; p != elements;)
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
StrVec::StrVec(const StrVec &s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec& StrVec::operator = (const StrVec &s)
{
auto data = alloc_n_copy(s.begin(), s.end());
free();//干掉左侧的
elements = data.first;
first_free = cap = data.second;
return *this;
}
StrVec& StrVec::operator = (StrVec &&s)
{
if (this != &s) {
free();
elements = s.elements;
first_free = s.first_free;
cap = s.cap;
s.elements = s.first_free = s.cap = nullptr;
}
return *this;
}
void StrVec::reallocate()
{
auto newcapacity = size() ? 2 * (size()) : 1;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));//调用move表示希望用 string的移动构造函数
free();//移动完元素后释放旧内存
//
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
//
void StrVec::reallocate()
{
auto newcapacity = size() ? 2 * size() : 1;
auto first = alloc.allocate(newcapacity);
//移动构造,uninitialized_copy 调用 construct将元素 移动构造
auto last = uninitialized_copy(make_move_iterator(begin()), make_move_iterator(end()), first);
free();
elements = first;
first_free = last;
cap = elements + newcapacity;
}
void StrVec::reallocate(size_t newcapacity)
{
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i < size(); i++)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
StrVec::StrVec(initializer_list<string> v1)
{
auto newdata = alloc_n_copy(v1.begin(), v1.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
void StrVec::reserve(size_t t)
{
if (t > capacity())
reallocate(t);
}
void StrVec::resize(size_t n)
{
if (n > size())
while (size() < n)
push_back("");
else if (n < size()) {
while (size() > n)
alloc.destroy(--first_free);
}
}
void StrVec::resize(size_t n, const string &s)
{
if (n > size()) {
while (size() < n)
push_back(s);
}
}
#endif // !STRVEC_H