StrVec.h:
#pragma once
#include <string>
#include <memory>
class StrVec
{
public:
StrVec();
StrVec(const StrVec &);
StrVec &operator=(const StrVec &);
StrVec(StrVec &&) noexcept;
StrVec &operator=(StrVec &&) noexcept;
~StrVec();
void push_back(const std::string &s);
size_t size() const;
size_t capacity() const;
std::string *begin() const;
std::string *end() const;
void reserve(size_t n);
void resize(size_t n, const std::string &s = std::string());
void push_back(std::string &&s);
private:
void check_volume();
void reallocate();
void free();
std::pair<std::string *, std::string *>
alloc_n_copy(const std::string *, const std::string *);
std::string *elements;
std::string *first_free;
std::string *cap;
static std::allocator<std::string> alloc;
};
StrVec.cpp:
#include "stdafx.h"
#include <iostream>
#include "StrVec.h"
std::allocator<std::string> StrVec::alloc = std::allocator<std::string>();
StrVec::StrVec()
: elements(nullptr), first_free(nullptr), cap(nullptr) {
std::cout << "Default constructor" << std::endl;
}
StrVec::StrVec(const StrVec &s) {
std::cout << "Copy constructor" << std::endl;
auto newBegin = alloc_n_copy(s.begin(), s.end());
elements = newBegin.first;
cap = first_free = newBegin.second;
}
StrVec &StrVec::operator=(const StrVec &rhs) {
std::cout << "Assign operator" << std::endl;
auto newBegin = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = newBegin.first;
cap = first_free = newBegin.second;
return *this;
}
StrVec::StrVec(StrVec &&s) noexcept {
std::cout << "Move constructor" << std::endl;
elements = s.elements;
first_free = s.first_free;
cap = s.cap;
s.elements = s.first_free = s.cap = nullptr;
}
StrVec &StrVec::operator=(StrVec &&rhs) noexcept {
std::cout << "Move operator" << std::endl;
if (this != &rhs) {
free();
elements = rhs.elements;
first_free = rhs.first_free;
cap = rhs.cap;
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return *this;
}
StrVec::~StrVec() {
free();
}
void StrVec::push_back(std::string &&s) {
check_volume();
alloc.construct(first_free++, std::move(s));
}
std::pair<std::string *, std::string *>
StrVec::alloc_n_copy(const std::string *b, const std::string *e) {
auto newMem = alloc.allocate(e - b);
return{ newMem, std::uninitialized_copy(b, e, newMem) };
}
void StrVec::reallocate() {
size_t newSize = size() ? 2 * size() : 1;
auto first = alloc.allocate(newSize);
auto last = uninitialized_copy(make_move_iterator(begin()),
make_move_iterator(end()),
first);
free();
elements = first;
first_free = newPos;
cap = first + newSize;
}
size_t StrVec::size() const {
return first_free - elements;
}
size_t StrVec::capacity() const {
return cap - elements;
}
void StrVec::push_back(const std::string &s) {
check_volume();
alloc.construct(first_free++, s);
}
std::string *StrVec::begin() const {
return elements;
}
std::string *StrVec::end() const {
return first_free;
}
void StrVec::check_volume() {
if (size() == capacity()) reallocate();
}
void StrVec::free() {
if (elements) {
for (auto p = first_free; p != elements;) {
alloc.destroy(--p); // should be destroy(--p); p point to the position after last elements, destroy a uninitialize pointer will lead to undefined behavior
}
alloc.deallocate(elements, cap - elements);
}
}
void StrVec::reserve(size_t n) {
if (n > size()) {
std::string *newBegin = alloc.allocate(n);
std::string *new_first_free = std::uninitialized_copy(begin(), end(), newBegin);
free();
first_free = new_first_free;
elements = newBegin;
cap = newBegin + n;
}
}
void StrVec::resize(size_t n, const std::string &s) {
std::string *newBegin = alloc.allocate(n);
std::string *new_first_free = nullptr;
if (n > size()) {
auto p = std::uninitialized_copy(begin(), end(), newBegin);
for (size_t i = 0; i < n - size(); ++i) {
alloc.construct(p++, s);
}
new_first_free = p;
}
else {
new_first_free = std::uninitialized_copy(begin(), begin() + n, newBegin);
}
first_free = new_first_free;
elements = newBegin;
cap = newBegin + n;
}
main.cpp:
using namespace std;
int main()
{
StrVec a;
a.push_back("abc");
StrVec b;
cout << b.size() << endl;
b = a;
StrVec c(std::move(b));
a = std::move(c);
return 0;
}
程序执行时出现failed:
C:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0 Line: 100
Expression: "(_Ptr_user &(_BIG_ALLOCATION_ALIGNMENT -1)) == 0" && 0
stackoverflow问题链接:
https://stackoverflow.com/questions/58341713/get-error-about-debug-assertion-failed-expression-ptr-user-big-allocatio