【足迹C++primer】47、Moving Objects(2)

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:现在的感觉是很不爽,不知道学这玩意什么时候才能去找工作,不知道去那好,还是耐心点,耐着性子,只要默默地向自己的目标前进就好,未来有我的机遇等着我,我现在要做的就是在机遇来的时候我可以狠狠的抓住!!!以免后悔一生

时间: 2024-07-29 20:36:36

【足迹C++primer】47、Moving Objects(2)的相关文章

【足迹C++primer】47、Moving Objects(1)

Moving Objects(1) * 功能:Moving Objects * 时间:2014年7月17日08:46:45 * 作者:cutter_point */ #include<iostream> #include<string> #include<memory> #include<utility> #include<vector> #include<algorithm> #include<set> #include

【足迹C++primer】33、再探迭代器

再探迭代器 这里有插入迭代器,有流迭代器,反向迭代器,移动迭代器. 插入迭代器 这是一种迭代器适配器,接受一个容器,生成一个迭代器,实现向给定容器添加元素. 插入迭代器有三种类型,差异在于元素插入的位置 back_inserter创建一个使用push_back的迭代器. front_inserter创建一个使用push_front的迭代器. inserter创建一个使用insert的迭代器. void fun1() { list<int> lst={1,2,3,4}; list<int&

【足迹C++primer】22、文件输入输出

文件输入输出 使用文件流对象 创建文件流对象时,我们可以提供文件名(可选).如果提供了一个文件名,则open会自动被调用: ifstream in(ifile); //构造一个ifstream并打开给定文件 ofstream out; //输出文件流未关联到任何文件 用fstream代替iostream& 首先这里有一个头文件和一个定义的文件要使用 Sales_data.h #ifndef SALES_DATA_H_INCLUDED #define SALES_DATA_H_INCLUDED #

【足迹C++primer】42、拷贝、赋值与销毁(1)

拷贝.赋值与销毁(1) 13.1.1拷贝构造函数 /************************************** 13.1.1拷贝构造函数 **************************************/ class Foo1 { public: Foo1(); //默认构造函数 Foo1(const Foo1&); //拷贝构造函数 //... }; 注意:拷贝构造函数的第一个参数必须是一个参数 合成拷贝构造函数 /************************

【足迹C++primer】38、关联容器操作(2)

关联容器操作(2) map的下标操作 map的下标操作 map和unordered_map容器提供了下标运算符合一个对应的at函数 对于一个map使用下标操作,其行为与数组或vector上的下标操作很不相同: 使用一个不再容器中的关键字作为下标,会添加一个此关键字的元素到map中 map和unordered_map的下标操作 c[k] 返回关键字为k的元素,如果关键字k不再c中,添加一个关键字为k的元素,对其进行值初始化 c.at(k) 访问关键字为k的元素,带参数检测,如果k不再c重那么返回一

【足迹C++primer】表达式求值

表达式求值 /** * 功能:表达式求值(0到9) * 时间:2014年6月15日08:02:31 * 作者:cutter_point */ #include<stdlib.h> #include<stack> #include<iostream> #include<string> using namespace std; stack<int> intStack; //存放数值的栈 stack<char> charStack; //存

【足迹C++primer】27、vector对象是如何增长的

vector对象是如何增长的 当需要更多空间的时候,会重新分配比新空间需求更大的内存空间,作为备用 管理容器的成员函数 shrink_to_fit //只适用于vector,string,deque capacity reserve //只适用于vector,string c.shrink_to_fit() //请将capacity()减少为与size相同大小 c.capacity() //不重新分配内存空间的话,c可以保存多少元素 c.reserve(n) //分配至少能容纳n个元素的内存空间

【足迹C++primer】41、文本查询程序

/** * 功能:使用标准库:文本查询程序 * 时间:2014年7月10日09:10:15 * 作者:cutter_point */ #include<iostream> #include<map> #include<set> #include<fstream> #include<sstream> #include<string> #include<vector> #include<memory> using

【足迹C++primer】28、额外的string操作

额外的string操作 构造string的其他方法 //n, len2, pos2 都是无符号值 string s(cp, n) //s是cp指向的数组中前n个字符的拷贝.此数组至少应该包含n个字符 string s(s2, pos2) //s是string s2从下标pos2开始的字符的拷贝. string s(s2, pos2, len2) //s是s2从pos2开始Len2个字符 const char *cp="Hello World!!!"; //以空字符结束的数组 char