From 828dc146b243517c52f484ba87da560c901a9e8d Mon Sep 17 00:00:00 2001 From: pezy Date: Tue, 3 Feb 2015 20:27:03 +0800 Subject: [PATCH] added ex13_39 --- ch13/README.md | 4 +- ch13/ex13_39.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ ch13/ex13_39.h | 51 +++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 ch13/ex13_39.cpp create mode 100644 ch13/ex13_39.h diff --git a/ch13/README.md b/ch13/README.md index 9d2cda8e..035686b1 100644 --- a/ch13/README.md +++ b/ch13/README.md @@ -223,4 +223,6 @@ some existing `Folders` will out of sync with the `Message` after assignment. The copy and swap is an elegant way when working with dynamicly allocated memory. In the Message class ,noing is allocated dynamically. Thus using this idiom makes no sense and will make it more complicated to implement due to the pointers that point back. @pezy -In this case, `swap` function is special. It will be clear two `Message`'s folders , then swap members, and added themselves to each folders. But, `Message` assignment operator just clear itself, and copy the members, and added itself to each folders. The `rhs` don't need to clear and add to folders. So, if using copy and swap to define, it will be very inefficiency. \ No newline at end of file +In this case, `swap` function is special. It will be clear two `Message`'s folders , then swap members, and added themselves to each folders. But, `Message` assignment operator just clear itself, and copy the members, and added itself to each folders. The `rhs` don't need to clear and add to folders. So, if using copy and swap to define, it will be very inefficiency. + +## Exercise 13.39 [hpp](ex13_39.h) | [cpp](ex13_39.cpp) \ No newline at end of file diff --git a/ch13/ex13_39.cpp b/ch13/ex13_39.cpp new file mode 100644 index 00000000..a756f4fc --- /dev/null +++ b/ch13/ex13_39.cpp @@ -0,0 +1,98 @@ +// +// ex13_39.cpp +// Exercise 13.39 +// +// Created by pezy on 2/3/15. +// Copyright (c) 2015 pezy. All rights reserved. +// +// Write your own version of StrVec, including versions of +// reserve, capacity (9.4, p. 356), and resize (9.3.5, p. 352). +// + +#include "StrVec.h" + +void StrVec::push_back(const std::string &s) +{ + chk_n_alloc(); + alloc.construct(first_free++, s); +} + +std::pair +StrVec::alloc_n_copy(const std::string *b, const std::string *e) +{ + auto data = alloc.allocate(e-b); + return { data, std::uninitialized_copy(b, e, data) }; +} + +void StrVec::free() +{ + if (elements) { + for (auto p = first_free; p != elements;) + alloc.destroy(--p); + alloc.deallocate(elements, cap - elements); + } +} + +StrVec::StrVec(const StrVec &rhs) +{ + auto newdata = alloc_n_copy(rhs.begin(), rhs.end()); + elements = newdata.first; + first_free = cap = newdata.second; +} + +StrVec::~StrVec() +{ + free(); +} + +StrVec& StrVec::operator = (const StrVec &rhs) +{ + auto data = alloc_n_copy(rhs.begin(), rhs.end()); + free(); + elements = data.first; + first_free = cap = data.second; + return *this; +} + +void StrVec::alloc_n_move(size_t new_cap) +{ + auto newdata = alloc.allocate(new_cap); + 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 + new_cap; +} + +void StrVec::reallocate() +{ + auto newcapacity = size() ? 2 * size() : 1; + alloc_n_move(newcapacity); +} + +void StrVec::reserve(size_t new_cap) +{ + if (new_cap <= capacity()) return; + alloc_n_move(new_cap); +} + +void StrVec::resize(size_t count) +{ + resize(count, std::string()); +} + +void StrVec::resize(size_t count, const std::string &s) +{ + if (count > size()) { + if (count > capacity()) reserve(count * 2); + for (size_t i = size(); i != count; ++i) + alloc.construct(first_free++, s); + } + else if (count < size()) { + while (first_free != elements + count) + alloc.destroy(--first_free); + } +} diff --git a/ch13/ex13_39.h b/ch13/ex13_39.h new file mode 100644 index 00000000..007d9bb1 --- /dev/null +++ b/ch13/ex13_39.h @@ -0,0 +1,51 @@ +// +// ex13_39.h +// Exercise 13.39 +// +// Created by pezy on 2/3/15. +// Copyright (c) 2015 pezy. All rights reserved. +// +// Write your own version of StrVec, including versions of +// reserve, capacity (9.4, p. 356), and resize (9.3.5, p. 352). +// + +#ifndef CP5_EX_13_39_H_ +#define CP5_EX_13_39_H_ + +#include +#include + +class StrVec +{ +public: + StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {} + StrVec(const StrVec&); + StrVec& operator=(const StrVec&); + ~StrVec(); + + void push_back(const std::string&); + size_t size() const { return first_free - elements; } + size_t capacity() const { return cap - elements; } + std::string *begin() const { return elements; } + std::string *end() const { return first_free; } + + void reserve(size_t new_cap); + void resize(size_t count); + void resize(size_t count, const std::string&); + +private: + std::pair alloc_n_copy(const std::string*, const std::string*); + void free(); + void chk_n_alloc() { if (size() == capacity()) reallocate(); } + void reallocate(); + void alloc_n_move(size_t new_cap); + +private: + std::string *elements; + std::string *first_free; + std::string *cap; + std::allocator alloc; +}; + +#endif +