Moving Objects(2)
Rvalue References and Member Functions
StrVec.h
#ifndef STRVEC_H #define STRVEC_H #include <iostream> #include <memory> #include <utility> // simplified implementation of the memory allocation strategy for a vector-like class class StrVec { public: // copy control members StrVec(): elements(0), first_free(0), cap(0) { } StrVec(const StrVec&); // copy constructor StrVec &operator=(const StrVec&); // copy assignment ~StrVec(); // destructor // additional constructor StrVec(const std::string*, const std::string*); void push_back(const std::string&); // copy the element void push_back(std::string&&); //move the element // add elements size_t size() const { return first_free - elements; } size_t capacity() const { return cap - elements; } // iterator interface std::string *begin() const { return elements; } std::string *end() const { return first_free; } // operator functions covered in chapter 14 std::string& operator[](std::size_t n) { return elements[n]; } const std::string& operator[](std::size_t n) const { return elements[n]; } private: static std::allocator<std::string> alloc; // allocates the elements // utility functions: // used by members that add elements to the StrVec void chk_n_alloc() { if (size() == capacity()) reallocate(); } // used by the copy constructor, assignment operator, and destructor std::pair<std::string*, std::string*> alloc_n_copy (const std::string*, const std::string*); void free(); // destroy the elements and free the space void reallocate(); // get more space and copy the existing elements std::string *elements; // pointer to the first element in the array std::string *first_free; // pointer to the first free element in the array std::string *cap; // pointer to one past the end of the array }; #include <algorithm> inline StrVec::~StrVec() { free(); } inline std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string *b, const std::string *e) { // allocate space to hold as many elements as are in the range std::string *data = alloc.allocate(e - b); // initialize and return a pair constructed from data and // the value returned by uninitialized_copy return std::make_pair(data, uninitialized_copy(b, e, data)); } inline StrVec::StrVec(const StrVec &s) { // call alloc_n_copy to allocate exactly as many elements as in s std::pair<std::string*, std::string*> newdata = alloc_n_copy(s.begin(), s.end()); elements = newdata.first; first_free = cap = newdata.second; } inline void StrVec::free() { // may not pass deallocate a 0 pointer; if elements is 0, there's no work to do if (elements) { // destroy the old elements in reverse order for (std::string *p = first_free; p != elements; /* empty */) alloc.destroy(--p); alloc.deallocate(elements, cap - elements); } } inline StrVec &StrVec::operator=(const StrVec &rhs) { // call alloc_n_copy to allocate exactly as many elements as in rhs std::pair<std::string*, std::string*> data = alloc_n_copy(rhs.begin(), rhs.end()); free(); elements = data.first; first_free = cap = data.second; return *this; } inline void StrVec::reallocate() { // we'll allocate space for twice as many elements as the current size size_t newcapacity = size() ? 2 * size() : 1; // allocate new memory std::string *newdata = alloc.allocate(newcapacity); // copy the data from the old memory to the new std::string *dest = newdata; // points to the next free position in the new array std::string *elem = elements; // points to the next element in the old array for (size_t i = 0; i != size(); ++i) alloc.construct(dest++, *elem++); free(); // free the old space once we've moved the elements // update our data structure to point to the new elements elements = newdata; first_free = dest; cap = elements + newcapacity; } inline StrVec::StrVec(const std::string *b, const std::string *e) { // call alloc_n_copy to allocate exactly as many elements as in il std::pair<std::string*, std::string*> newdata = alloc_n_copy(b, e); elements = newdata.first; first_free = cap = newdata.second; } #endif
StrVec.cc
#include "StrVec.h" #include <string> #include <utility> // errata fixed in second printing -- // StrVec's allocator should be a static member not an ordinary member // definition for static data member std::allocator<std::string> StrVec::alloc; // all other StrVec members are inline and defined inside StrVec.h
inline void StrVec::push_back(const string& s) { chk_n_alloc(); // ensure that there is room for another element // construct a copy of s in the element to which first_free points alloc.construct(first_free++, s); } inline void StrVec::push_back(string&& s) { chk_n_alloc(); alloc.construct(first_free++, std::move(s)); } void fun1() { StrVec vec; string s="my name is cutter_point!"; vec.push_back(s); //调用const string&这个 vec.push_back("China!"); //调用string&& }
class Foo { public: Foo()=default; Foo(const Foo&); //copy构造函数 Foo &operator=(const Foo&) &; //返回一个左值&&表示返回右值 // Foo someMem() & const; //错误,const应放第一位 Foo anotherMem() const &; //正确 }; Foo &Foo::operator=(const Foo &rhs) & { return *this; } Foo::Foo(const Foo &f) { } void fun2() { Foo &retFoo(); //返回一个引用,是一个左值 Foo retVal(); //返回一个值,右值调用 Foo i, j; //i,j是左值 i=j; //i是左值 // retFoo()=j; //OK这个返回的是一个左值 // retVal()=j; //错误。retVal是一个右值 }
Overloading and Reference Functions
class Foo { public: Foo()=default; // Foo(const Foo&); //copy构造函数 // Foo(Foo&&); Foo &operator=(const Foo&) &; //返回一个左值&&表示返回右值 // Foo someMem() & const; //错误,const应放第一位 Foo anotherMem() const &; //正确 Foo sorted() &&; //返回右值 Foo sorted() const &; //返回左值 private: vector<int> data; }; Foo Foo::sorted() && { sort(data.begin(), data.end()); return *this; } Foo Foo::sorted() const & { Foo ret(*this); sort(ret.data.begin(), ret.data.end()); return ret; }
int main() { string s1="a value", s2="this is a pig."; auto n=(s1+s2).find('e'); cout<<n<<endl; return 0; }
PS:现在的感觉是很不爽,不知道学这玩意什么时候才能去找工作,不知道去那好,还是耐心点,耐着性子,只要默默地向自己的目标前进就好,未来有我的机遇等着我,我现在要做的就是在机遇来的时候我可以狠狠的抓住!!!以免后悔一生