From 26277c8ab34344fb20d546ac1b1dd51058a233dd Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Fri, 25 Apr 2014 08:18:07 -0700 Subject: [PATCH] Implement move assignment operator for Array. --- format-test.cc | 6 ++++-- format.cc | 1 - format.h | 46 ++++++++++++++++++++++++++++++++-------------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/format-test.cc b/format-test.cc index e8778f95..de715d59 100644 --- a/format-test.cc +++ b/format-test.cc @@ -226,12 +226,13 @@ TEST(ArrayTest, MoveCtor) { // dynamic allocation. array.push_back('a'); CheckMoveArray("testa", array); + const char *inline_buffer_ptr = &array[0]; // Adding one more character causes the content to move from the inline to // a dynamically allocated buffer. array.push_back('b'); Array array2(std::move(array)); // Move should rip the guts of the first array. - EXPECT_TRUE(!&array[0]); + EXPECT_EQ(inline_buffer_ptr, &array[0]); EXPECT_EQ("testab", std::string(&array2[0], array2.size())); EXPECT_GT(array2.capacity(), 5); } @@ -335,12 +336,13 @@ TEST(WriterTest, MoveCtor) { w.Clear(); w << s; CheckMoveWriter(s, w); + const char *inline_buffer_ptr = w.data(); // Adding one more character causes the content to move from the inline to // a dynamically allocated buffer. w << '*'; Writer w2(std::move(w)); // Move should rip the guts of the first writer. - EXPECT_TRUE(!w.data()); + EXPECT_EQ(inline_buffer_ptr, w.data()); EXPECT_EQ(s + '*', w2.str()); } diff --git a/format.cc b/format.cc index 56c93cc4..6207fe57 100644 --- a/format.cc +++ b/format.cc @@ -33,7 +33,6 @@ #include "format.h" -#include #include #include #include diff --git a/format.h b/format.h index 3c00294b..078b1c9a 100644 --- a/format.h +++ b/format.h @@ -30,6 +30,7 @@ #include +#include #include // for std::ptrdiff_t #include #include @@ -143,30 +144,47 @@ class Array { void Grow(std::size_t size); + // Free memory allocated by the array. + void Free() { + if (ptr_ != data_) delete [] ptr_; + } + + // Move data from other to this array. + void Move(Array &other) { + size_ = other.size_; + capacity_ = other.capacity_; + if (other.ptr_ == other.data_) { + ptr_ = data_; + std::copy(other.data_, other.data_ + size_, CheckPtr(data_, capacity_)); + } else { + ptr_ = other.ptr_; + // Set pointer to the inline array so that delete is not called + // when freeing. + other.ptr_ = other.data_; + } + } + // Do not implement! Array(const Array &); void operator=(const Array &); public: Array() : size_(0), capacity_(SIZE), ptr_(data_) {} - ~Array() { - if (ptr_ != data_) delete [] ptr_; - } + ~Array() { Free(); } #if FMT_USE_RVALUE_REFERENCES - Array(Array &&other) - : size_(other.size_), - capacity_(other.capacity_) { - if (other.ptr_ == other.data_) { - ptr_ = data_; - std::copy(other.data_, other.data_ + size_, CheckPtr(data_, capacity_)); - } else { - ptr_ = other.ptr_; - other.ptr_ = 0; - } + + Array(Array &&other) { + Move(other); + } + + Array& operator=(Array&& other) { + assert(this != &other); + Free(); + Move(other); + return *this; } - // TODO: move assignment operator #endif // Returns the size of this array.