C++Primer第五版 习题答案(部分) 第十四章 运算符重载与类型转换

14.2

#include<string>
#include<iostream>

struct Sales_data;
std::istream& operator>>(std::istream& is, Sales_data& item);
std::ostream& operator<<(std::ostream& os, const Sales_data& item);
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs);


class Sales_data
{

friend	std::istream &operator>>(std::istream&, Sales_data&);
friend	std::ostream &operator<<(std::ostream&, Sales_data&);
friend	Sales_data operator+(const Sales_data&, const Sales_data&);
public:
	Sales_data(const std::string& s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(p* n) 
	{ std::cout << "Sales_data(const std::string& s, unsigned n, double p)" << std::endl; }
	Sales_data() :Sales_data("", 0, 0) 
	{ std::cout << "Sales_data() :Sales_data("", 0, 0)" << std::endl; }
	Sales_data(const std::string& s) :Sales_data(s, 0, 0) 
	{ std::cout << "Sales_data(const std::string& s):Sales_data(s, 0, 0)" << std::endl; }
	Sales_data(std::istream& is) :Sales_data() 
	{ is >> *this; std::cout << "Sales_data(std::istream& is) :Sales_data() " << std::endl; }
	std::string isbn() const { return bookNo; }
	Sales_data& operator+=(const Sales_data&);
private:
	inline double avg_price()const;
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

inline double Sales_data::avg_price()const
{
	if (units_sold)
		return revenue / units_sold;
	else
		return 0;
}
Sales_data& Sales_data::operator+=(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}

std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	if (is)
		item.revenue = price * item.units_sold;
	else
		item = Sales_data();
	return is;
}

std::ostream& operator<<(std::ostream& os,  Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
	return os;
}

Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum += rhs;
	return sum;

}

int main()
{
	Sales_data sales_data1("12313", 2, 5);
	Sales_data sales_data2;
	Sales_data sales_data3("12135");
	Sales_data sale_data4(std::cin);
	return 0;
}

14.5

aaa.h

#ifndef CP5_CH14_EX14_05_H
#define CP5_CH14_EX14_05_H

#include <iostream>
#include <string>



class Book {

	friend std::istream& operator>>(std::istream&, Book&);
	friend std::ostream& operator<<(std::ostream&, const Book&);
	friend bool operator==(const Book&, const Book&);
	friend bool operator!=(const Book&, const Book&);

public:
	Book() = default;
	Book(unsigned no, std::string name, std::string author, std::string pubdate)
		:no_(no),name_(name),author_(author),pubdate_(pubdate) {}
	Book(std::istream& in) { in >> *this; }

private:
	unsigned no_;
	std::string name_;
	std::string author_;
	std::string pubdate_;
};

std::istream& operator>>(std::istream&, Book&);
std::ostream& operator<<(std::ostream&, const Book&);
bool operator==(const Book&, const Book&);
bool operator!=(const Book&, const Book&);

#endif // CP5_CH14_EX14_05_H

aaa.cpp

#include"aaa.h"

std::istream& operator>>(std::istream&in, Book&book)
{
	in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
	return in;
}

std::ostream& operator<<(std::ostream&out, const Book&book)
{
	out << book.no_ << book.name_ << book.author_ << book.pubdate_;
	return out;
   
}

bool operator==(const Book& lhs, const Book& rhs)
{
	return  lhs.no_ == rhs.no_;
}
bool operator!=(const Book&lhs, const Book&rhs)
{
	return!(lhs == rhs);
}

main

#include"aaa.h"
int main()
{
	Book book1{ 123,"az","jack","2020" };
	Book book2{ 123,"sa","jack","2021" };
	if (book1 == book2)
	{
		std::cout << book1 << std::endl;

	}

	return 0;
}

14.7

ostream &operator<<(ostream &os,const string &s)
{
for(auto iter =s.elements;it!=s.first_free;++it)
{
os<<*iter;
}
return os;
}

14.9

istream &operator>>(istream &is,Sales_data &iteam)
{
double price;
is>>item.bookNo>>item.units_sold>>price;
if(is)
{
item.revenue = item.units_sold*price;
}
else
{
item =Sales_data();
}
return is;
}

14.19



#include <iostream>
#include <string>

class Book {
    friend std::istream& operator>>(std::istream&, Book&);
    friend std::ostream& operator<<(std::ostream&, const Book&);
    friend bool operator==(const Book&, const Book&);
    friend bool operator!=(const Book&, const Book&);
    friend bool operator<(const Book&, const Book&);
    friend bool operator>(const Book&, const Book&);
    friend bool operator<=(const Book&, const Book&);
    friend bool operator>=(const Book&, const Book&);

public:
    Book() = default;
    Book(unsigned no, std::string name, std::string author, std::string pubdate) :no_(no), name_(name), author_(author), pubdate_(pubdate) { }
    Book(std::istream& in) { in >> *this; }

private:
    unsigned int no_;
    std::string name_;
    std::string author_;
    std::string pubdate_;
};

std::istream& operator>>(std::istream& in, Book& book)
{
    in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
    return in;
}

std::ostream& operator<<(std::ostream& out, const Book& book)
{
    out << book.no_ << " " << book.name_ << " " << book.author_ << " " << book.pubdate_;
    return out;
}

bool operator==(const Book& lhs, const Book& rhs)
{
    return lhs.no_ == rhs.no_;
}

bool operator!=(const Book& lhs, const Book& rhs)
{
    return !(lhs == rhs);
}

bool operator<(const Book& lhs, const Book& rhs)
{
    return lhs.no_ < rhs.no_;
}

bool operator>(const Book& lhs, const Book& rhs)
{
    return rhs < lhs;
}

bool operator<=(const Book& lhs, const Book& rhs)
{
    return !(rhs < lhs);
}

bool operator>=(const Book& lhs, const Book& rhs)
{
    return !(lhs < rhs);
}

int main()
{
    Book book1(123, "CP5", "Lippman", "2012");
    Book book2(123, "CP5", "Lippman", "2012");

    if (book1 == book2)
        std::cout << book1 << std::endl;
}

14.20

Sales_data& Sales_data::operator+(const Sales_data &rhs)
{
    Sales_data old_data = *this;
    *this = old_data + rhs;
    return *this;
}

Sales_data operator+=(const Sales_data &lhs, const Sales_data &rhs)
{
    Sales_data sum;
    sum.units_sold = lhs.units_sold + rhs.units_sold;
    sum.revenue = lhs.revenue + rhs.revenue;
    return sum;
}

14.21

本题的+和+=都用到了临时变量;

14.22


#include<iostream>
#include <string>

struct Sales_data;

std::istream& operator>>(std::istream& is, Sales_data& item);
std::ostream& operator<<(std::ostream& os, const Sales_data& item);
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs);

struct Sales_data
{
	friend std::istream& operator>>(std::istream&, Sales_data&);
	friend std::ostream& operator<<(std::ostream&, const Sales_data&);
	friend Sales_data operator+(const Sales_data&, const Sales_data&);
public:
	Sales_data(const std::string& s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p* n) { std::cout << "Sales_data(const std::string &s, unsigned n, double p)" << std::endl; }
	Sales_data() : Sales_data("", 0, 0) { std::cout << "Sales_data() : Sales_data(\"\", 0, 0)" << std::endl; }
	Sales_data(const std::string& s) : Sales_data(s, 0, 0) { std::cout << "Sales_data(const std::string &s) : Sales_data" << std::endl; }
	Sales_data(std::istream& is) : Sales_data() {/*read(is, *this);*/ is >> *this; std::cout << "Sales_data(std::istream &is) : Sales_data()" << std::endl; }
	std::string isbn() const { return bookNo; }
	Sales_data& operator=(const std::string&);
	Sales_data& operator+=(const Sales_data&);
	Sales_data& operator-=(const Sales_data&);
private:
	inline double avg_price() const;

	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

inline double Sales_data::avg_price() const
{
	if (units_sold)
		return revenue / units_sold;
	else
		return 0;
}

Sales_data& Sales_data::operator=(const std::string& s)
{
	*this = Sales_data(s);
	return *this;
}

Sales_data& Sales_data::operator+=(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;

	return *this;
}

Sales_data& Sales_data::operator-=(const Sales_data& rhs)
{
	units_sold -= rhs.units_sold;
	revenue -= rhs.revenue;

	return *this;
}

std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;

	is >> item.bookNo >> item.units_sold >> price;
	if (is)
		item.revenue = price * item.units_sold;
	else
		item = Sales_data();

	return is;
}

std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();

	return os;
}

Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum += rhs;
	return sum;
}

int main()
{
	return 0;
}


14.23

#include <string>
#include <utility>
#include <memory>
#include <algorithm>

class StrVec
{
	friend bool operator==(StrVec& lhs, StrVec& rhs);
	friend bool operator!=(StrVec& lhs, StrVec& rhs);
	friend bool operator<(StrVec& lhs, StrVec& rhs);
	friend bool operator>(StrVec& lhs, StrVec& rhs);
	friend bool operator<=(StrVec& lhs, StrVec& rhs);
	friend bool operator>=(StrVec& lhs, StrVec& rhs);

public:
	StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }
	StrVec(std::initializer_list<std::string>);
	StrVec(const StrVec&);
	StrVec(StrVec&& s) noexcept : alloc(std::move(s.alloc)), elements(std::move(s.elements)), first_free(std::move(s.first_free)), cap(std::move(s.cap)) { s.elements = s.first_free = s.cap = nullptr; }
	StrVec& operator=(const StrVec&);
	StrVec& operator=(StrVec&&) noexcept;
	StrVec& operator=(std::initializer_list<std::string>);
	~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 n);
	void resize(size_t n);
	void resize(size_t n, const std::string& s);
private:
	std::allocator<std::string> alloc;
	void chk_n_alloc() { if (size() == capacity()) reallocate(); }
	std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);
	void free();
	void reallocate();
	std::string* elements;
	std::string* first_free;
	std::string* cap;
};

StrVec::StrVec(std::initializer_list<std::string> il)
{
	auto newdata = alloc_n_copy(il.begin(), il.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
}

void StrVec::push_back(const std::string& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, s);
}

std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b, const std::string* e)
{
	auto data = alloc.allocate(e - b);
	return { data, uninitialized_copy(b, e, data) };
}

void StrVec::free()
{
	if (elements)
	{
		std::for_each(elements, first_free, [this](std::string& p) { alloc.destroy(&p); });
		// for(auto p = first_free; p != elements; )
		// 	alloc.destroy(--p);
		alloc.deallocate(elements, cap - elements);
	}
}

StrVec::StrVec(const StrVec& s)
{
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
}

StrVec& StrVec::operator=(std::initializer_list<std::string> il)
{
	auto data = alloc_n_copy(il.begin(), il.end());
	free();
	elements = data.first;
	first_free = cap = data.second;
	return *this;
}

StrVec::~StrVec()
{
	free();
}

void StrVec::reserve(size_t n)
{
	if (n <= capacity()) return;
	auto newdata = alloc.allocate(n);
	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 + n;
}

void StrVec::resize(size_t n)
{
	resize(n, std::string());
}

void StrVec::resize(size_t n, const std::string& s)
{
	if (n < size())
	{
		while (n < size())
			alloc.destroy(--first_free);
	}
	else if (n > size())
	{
		while (n > size())
			push_back(s);
		// alloc.construct(first_free, s);
	}
}

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;
}

StrVec& StrVec::operator=(StrVec&& rhs) noexcept
{
	if (this != &rhs)
	{
		free();
		alloc = std::move(rhs.alloc);
		elements = std::move(rhs.elements);
		first_free = std::move(rhs.first_free);
		cap = std::move(rhs.cap);
		rhs.elements = rhs.first_free = rhs.cap = nullptr;
	}
	return *this;
}

void StrVec::reallocate()
{
	auto newcapacity = size() ? 2 * size() : 1;
	auto newdata = alloc.allocate(newcapacity);
	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 + newcapacity;
}

bool operator==(StrVec& lhs, StrVec& rhs)
{
	return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

bool operator!=(StrVec& lhs, StrVec& rhs)
{
	return !(lhs == rhs);
}

bool operator<(StrVec& lhs, StrVec& rhs)
{
	return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator>(StrVec& lhs, StrVec& rhs)
{
	return rhs < lhs;
}
bool operator<=(StrVec& lhs, StrVec& rhs)
{
	return !(rhs < lhs);
}
bool operator>=(StrVec& lhs, StrVec& rhs)
{
	return !(lhs < rhs);
}


int main()
{
	StrVec s({ "aaa","bbb" });
	return 0;
}

14.25



#include <iostream>
#include <string>

class Book {
    friend std::istream& operator>>(std::istream&, Book&);
    friend std::ostream& operator<<(std::ostream&, const Book&);
    friend bool operator==(const Book&, const Book&);
    friend bool operator!=(const Book&, const Book&);
    friend bool operator<(const Book&, const Book&);
    friend bool operator>(const Book&, const Book&);
    friend bool operator<=(const Book&, const Book&);
    friend bool operator>=(const Book&, const Book&);

public:
    Book() = default;
    Book(unsigned no, std::string name, std::string author, std::string pubdate) :no_(no), name_(name), author_(author), pubdate_(pubdate) { }
    Book(std::istream& in) { in >> *this; }
    //拷贝赋值
    Book& operator=(const Book&);
    //移动赋值
    Book& operator=(const Book&&)noexcept;
private:
    unsigned int no_;
    std::string name_;
    std::string author_;
    std::string pubdate_;
};

Book& Book::operator=(const Book& rhs)
{
    this->no_ = rhs.no_;
    this->name_ = rhs.name_;
    this->author_ = rhs.author_;
    this->pubdate_ = rhs.pubdate_;
    return *this;
}
Book& Book::operator=(const Book&& rhs)noexcept
{
if(this!=&rhs)
{ 
    this->no_ = rhs.no_;
    this->name_ = rhs.name_;
    this->author_ = rhs.author_;
    this->pubdate_ = rhs.pubdate_;
}
return* this;
}

std::istream& operator>>(std::istream& in, Book& book)
{
    in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
    return in;
}

std::ostream& operator<<(std::ostream& out, const Book& book)
{
    out << book.no_ << " " << book.name_ << " " << book.author_ << " " << book.pubdate_;
    return out;
}

bool operator==(const Book& lhs, const Book& rhs)
{
    return lhs.no_ == rhs.no_;
}

bool operator!=(const Book& lhs, const Book& rhs)
{
    return !(lhs == rhs);
}

bool operator<(const Book& lhs, const Book& rhs)
{
    return lhs.no_ < rhs.no_;
}

bool operator>(const Book& lhs, const Book& rhs)
{
    return rhs < lhs;
}

bool operator<=(const Book& lhs, const Book& rhs)
{
    return !(rhs < lhs);
}

bool operator>=(const Book& lhs, const Book& rhs)
{
    return !(lhs < rhs);
}

int main()
{
    Book book1(123, "CP5", "Lippman", "2012");
    Book book2(123, "CP5", "Lippman", "2012");

    if (book1 == book2)
        std::cout << book1 << std::endl;
}

14.26

StrBlob、StrBlobPtr

#include<iostream>
#include <string>
#include <initializer_list>
#include <memory>
#include <vector>
#include <stdexcept>

class ConstStrBlobPtr;

class StrBlob
{
	friend class ConstStrBlobPtr;
	friend bool operator==(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator!=(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator<(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator>(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator<=(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator>=(const StrBlob& lhs, const StrBlob& rhs);
public:
	typedef std::vector<std::string>::size_type size_type;
	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	StrBlob(const StrBlob&);
	StrBlob& operator=(const StrBlob&);
	size_type size() const { return data->size(); }
	bool empty() const { return data->empty(); }
	void push_back(const std::string& t) { data->push_back(t); }
	void push_back(std::string&& t) { data->push_back(t); }
	void pop_back();
	std::string& front();
	std::string& back();
	const std::string& front() const;
	const std::string& back() const;
	ConstStrBlobPtr begin();
	ConstStrBlobPtr end();
	std::string& operator[](size_t n) { return ( * data)[n]; }
	const std::string& operator[](size_t n) const { return (*data)[n]; }
private:
	std::shared_ptr<std::vector<std::string>> data;
	void check(size_type i, const std::string& msg) const;
};

class ConstStrBlobPtr
{
	friend bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs);
	friend bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs);

public:
	ConstStrBlobPtr() : curr(0) {};
	ConstStrBlobPtr(const StrBlob& a, size_t sz = 0) : wptr(a.data), curr(sz) {}
	std::string& deref() const;
	ConstStrBlobPtr& incr();
private:
	std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
	std::weak_ptr<std::vector<std::string>> wptr;
	std::size_t curr;
};

std::shared_ptr<std::vector<std::string>> ConstStrBlobPtr::check(std::size_t i, const std::string& msg) const
{
	auto ret = wptr.lock();
	if (!ret)
		throw std::runtime_error("unbound ConstStrBlobPtr");
	if (i >= ret->size())
		throw std::out_of_range(msg);
	return ret;
}

std::string& ConstStrBlobPtr::deref() const
{
	auto p = check(curr, "dereference past end");
	return (*p)[curr];
}

ConstStrBlobPtr& ConstStrBlobPtr::incr()
{
	check(curr, "increment past end of ConstStrBlobPtr");
	++curr;
	return *this;
}

StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il)) {}
StrBlob::StrBlob(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); }
StrBlob& StrBlob::operator=(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); return *this; }

void StrBlob::check(size_type i, const std::string& msg) const
{
	if (i >= data->size())
		throw std::out_of_range(msg);
}

std::string& StrBlob::front()
{
	check(0, "front on empty StrBlob");
	return data->front();
}

std::string& StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}

const std::string& StrBlob::front() const
{
	check(0, "front on empty StrBlob");
	return data->front();
}

const std::string& StrBlob::back() const
{
	check(0, "back on empty StrBlob");
	return data->back();
}

void StrBlob::pop_back()
{
	check(0, "pop_back on empty StrBlob");
	data->pop_back();
}

ConstStrBlobPtr StrBlob::begin() { return ConstStrBlobPtr(*this); }

ConstStrBlobPtr StrBlob::end()
{
	auto ret = ConstStrBlobPtr(*this, data->size());
	return ret;
}

bool operator==(const StrBlob& lhs, const StrBlob& rhs)
{
	return *lhs.data == *rhs.data;
}

bool operator!=(const StrBlob& lhs, const StrBlob& rhs)
{
	return !(lhs == rhs);
}
bool operator<(const StrBlob& lhs, const StrBlob& rhs)
{
	return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());
}

bool operator>(const StrBlob& lhs, const StrBlob& rhs)
{
	return rhs < lhs;
}

bool operator<=(const StrBlob& lhs, const StrBlob& rhs)
{
	return !(rhs < lhs);
}

bool operator>=(const StrBlob& lhs, const StrBlob& rhs)
{
	return !(lhs < rhs);
}


bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
	auto lret = lhs.wptr.lock(), rret = rhs.wptr.lock();
	return lret == rret && lhs.curr == rhs.curr;
}
bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
	return !(lhs == rhs);
}
int main()
{
	StrBlob b1 = { "a","aa","aaa" };
	StrBlob b2 = b1;
	return 0;
}

StrVec类

#include <string>
#include <utility>
#include <memory>
#include <algorithm>

class StrVec
{
	friend bool operator==(StrVec& lhs, StrVec& rhs);
	friend bool operator!=(StrVec& lhs, StrVec& rhs);
	friend bool operator<(StrVec& lhs, StrVec& rhs);
	friend bool operator>(StrVec& lhs, StrVec& rhs);
	friend bool operator<=(StrVec& lhs, StrVec& rhs);
	friend bool operator>=(StrVec& lhs, StrVec& rhs);

public:
	StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }
	StrVec(std::initializer_list<std::string>);
	StrVec(const StrVec&);
	StrVec(StrVec&& s) noexcept : alloc(std::move(s.alloc)), elements(std::move(s.elements)), first_free(std::move(s.first_free)), cap(std::move(s.cap)) { s.elements = s.first_free = s.cap = nullptr; }
	StrVec& operator=(const StrVec&);
	StrVec& operator=(StrVec&&) noexcept;
	std::string& operator[](std::size_t n) { return elements[n]; }
	const std::string& operator[](std::size_t n)const { return elements[n]; }

	~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 n);
	void resize(size_t n);
	void resize(size_t n, const std::string& s);
private:
	std::allocator<std::string> alloc;
	void chk_n_alloc() { if (size() == capacity()) reallocate(); }
	std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);
	void free();
	void reallocate();
	std::string* elements;
	std::string* first_free;
	std::string* cap;
};

StrVec::StrVec(std::initializer_list<std::string> il)
{
	auto newdata = alloc_n_copy(il.begin(), il.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
}

void StrVec::push_back(const std::string& s)
{
	chk_n_alloc();
	alloc.construct(first_free++, s);
}

std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b, const std::string* e)
{
	auto data = alloc.allocate(e - b);
	return { data, uninitialized_copy(b, e, data) };
}

void StrVec::free()
{
	if (elements)
	{
		std::for_each(elements, first_free, [this](std::string& p) { alloc.destroy(&p); });
		// for(auto p = first_free; p != elements; )
		// 	alloc.destroy(--p);
		alloc.deallocate(elements, cap - elements);
	}
}

StrVec::StrVec(const StrVec& s)
{
	auto newdata = alloc_n_copy(s.begin(), s.end());
	elements = newdata.first;
	first_free = cap = newdata.second;
}

StrVec::~StrVec()
{
	free();
}

void StrVec::reserve(size_t n)
{
	if (n <= capacity()) return;
	auto newdata = alloc.allocate(n);
	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 + n;
}

void StrVec::resize(size_t n)
{
	resize(n, std::string());
}

void StrVec::resize(size_t n, const std::string& s)
{
	if (n < size())
	{
		while (n < size())
			alloc.destroy(--first_free);
	}
	else if (n > size())
	{
		while (n > size())
			push_back(s);
		// alloc.construct(first_free, s);
	}
}

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;
}

StrVec& StrVec::operator=(StrVec&& rhs) noexcept
{
	if (this != &rhs)
	{
		free();
		alloc = std::move(rhs.alloc);
		elements = std::move(rhs.elements);
		first_free = std::move(rhs.first_free);
		cap = std::move(rhs.cap);
		rhs.elements = rhs.first_free = rhs.cap = nullptr;
	}
	return *this;
}

void StrVec::reallocate()
{
	auto newcapacity = size() ? 2 * size() : 1;
	auto newdata = alloc.allocate(newcapacity);
	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 + newcapacity;
}

bool operator==(StrVec& lhs, StrVec& rhs)
{
	return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

bool operator!=(StrVec& lhs, StrVec& rhs)
{
	return !(lhs == rhs);
}

bool operator<(StrVec& lhs, StrVec& rhs)
{
	return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator>(StrVec& lhs, StrVec& rhs)
{
	return rhs < lhs;
}
bool operator<=(StrVec& lhs, StrVec& rhs)
{
	return !(rhs < lhs);
}
bool operator>=(StrVec& lhs, StrVec& rhs)
{
	return !(lhs < rhs);
}


int main()
{
	StrVec s({ "aaa","bbb" });
	return 0;
}

String 类

#include<iostream>
#include <memory>
#include <algorithm>
#include <cstring>
#include <iostream>
#include<vector>

class String
{
	friend std::ostream& operator<<(std::ostream& os, const String& s);
	friend bool operator==(const String& lhs, const  String& rhs);
	friend bool operator!=(const String& lhs, const  String& rhs);
	friend bool operator<(const String& lhs, const  String& rhs);
	friend bool operator>(const String& lhs, const  String& rhs);
	friend bool operator<=(const String& lhs, const  String& rhs);
	friend bool operator>=(const String& lhs, const  String& rhs);
public:
	String();
	String(const char*);
	String(const String&);
	String(String&&) noexcept;
	String& operator=(const String&);
	String& operator=(String&&) noexcept;
	char* begin() const { return elements; }
	char* end() const { return first_free; }
	~String();
private:
	std::pair<char*, char*> alloc_n_copy(const char*, const char*);
	void free();

	std::allocator<char> alloc;
	char* elements;
	char* first_free;
};

std::pair<char*, char*> String::alloc_n_copy(const char* begin, const char* end)
{
	char* p = alloc.allocate(end - begin);
	return{ p, std::uninitialized_copy(begin, end, p) };
}

String::String(const char* cp)
{
	size_t n = strlen(cp);
	auto newstr = alloc_n_copy(cp, cp + n);
	elements = newstr.first;
	first_free = newstr.second;
}

String::String()
{
	String("");
}

String::String(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	elements = newstr.first;
	first_free = newstr.second;
	std::cout << "String(const String &rhs)" << std::endl;
}

String::String(String&& s) noexcept : alloc(std::move(s.alloc)), elements(std::move(s.elements)), first_free(std::move(s.first_free))
{
	std::cout << "String::String(String &&s) noexcept" << std::endl;
	s.elements = s.first_free = nullptr;
}

void String::free()
{
	if (elements)
	{
		std::for_each(elements, first_free, [this](char cp) { alloc.destroy(&cp); });
		alloc.deallocate(elements, first_free - elements);
	}
}

String& String::operator=(const String& rhs)
{
	auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
	free();
	elements = newstr.first;
	first_free = newstr.second;
	std::cout << "String& operator=(const String& rhs)" << std::endl;
	return *this;
}

String& String::operator=(String&& rhs) noexcept
{
	std::cout << "String& String::operator=(String &&rhs) noexcept" << std::endl;
	if (&rhs != this)
	{
		free();
		alloc = std::move(rhs.alloc);
		elements = std::move(rhs.elements);
		first_free = std::move(rhs.first_free);
		rhs.elements = rhs.first_free = nullptr;
	}
	return *this;
}

String::~String()
{
	free();
}

std::ostream& operator<<(std::ostream& os, const String& s)
{
	for (auto iter = s.elements; iter != s.first_free; ++iter)
	{
		os << *iter;
	}
	return os;
}
bool operator==(const String& lhs, const  String& rhs)
{

	return (lhs.first_free - lhs.elements) == (rhs.first_free - rhs.elements) && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
bool operator !=(const String& lhs, const  String& rhs)
{

	return!(lhs == rhs);
}
bool operator<(const String& lhs, const  String& rhs)
{
	return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator>(const String& lhs, const  String& rhs)
{
	return rhs<lhs;
}
bool operator<=(const String& lhs, const  String& rhs)
{
	return !(rhs < lhs);
}
bool operator>=(const String& lhs, const  String& rhs)
{
	return (lhs<rhs);
}

int main()
{
	std::vector<String>v;
	v.push_back("aaa");
	v.push_back("bbb");
	std::cout << v[1] << std::endl;

	return 0;

}

14.30

#include<iostream>
#include <string>
#include <initializer_list>
#include <memory>
#include <vector>
#include <stdexcept>

class ConstStrBlobPtr;

class StrBlob
{
	friend class ConstStrBlobPtr;
	friend bool operator==(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator!=(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator<(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator>(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator<=(const StrBlob& lhs, const StrBlob& rhs);
	friend bool operator>=(const StrBlob& lhs, const StrBlob& rhs);
public:
	typedef std::vector<std::string>::size_type size_type;
	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	StrBlob(const StrBlob&);
	StrBlob& operator=(const StrBlob&);
	size_type size() const { return data->size(); }
	bool empty() const { return data->empty(); }
	void push_back(const std::string& t) { data->push_back(t); }
	void push_back(std::string&& t) { data->push_back(t); }
	void pop_back();
	std::string& front();
	std::string& back();
	const std::string& front() const;
	const std::string& back() const;
	ConstStrBlobPtr begin();
	ConstStrBlobPtr end();
	std::string& operator[](size_t n) { return (*data)[n]; }
	const std::string& operator[](size_t n) const { return (*data)[n]; }
private:
	std::shared_ptr<std::vector<std::string>> data;
	void check(size_type i, const std::string& msg) const;
};

class ConstStrBlobPtr
{
	friend bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs);
	friend bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs);

public:
	ConstStrBlobPtr() : curr(0) {};
	ConstStrBlobPtr(const StrBlob& a, size_t sz = 0) : wptr(a.data), curr(sz) {}
	std::string& deref() const;
	ConstStrBlobPtr& incr();
	ConstStrBlobPtr& operator++();
	ConstStrBlobPtr& operator--();
	ConstStrBlobPtr operator++(int);
	ConstStrBlobPtr operator--(int);
	const std::string& operator*()const
	{
	
		auto p = check(curr, "dereference past end");
		return (*p)[curr];
	}
	const std::string* operator->()const
	{
		return &this->operator*();
		
	}


private:
	std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
	std::weak_ptr<std::vector<std::string>> wptr;
	std::size_t curr;
};

std::shared_ptr<std::vector<std::string>> ConstStrBlobPtr::check(std::size_t i, const std::string& msg) const
{
	auto ret = wptr.lock();
	if (!ret)
		throw std::runtime_error("unbound ConstStrBlobPtr");
	if (i >= ret->size())
		throw std::out_of_range(msg);
	return ret;
}

std::string& ConstStrBlobPtr::deref() const
{
	auto p = check(curr, "dereference past end");
	return (*p)[curr];
}

ConstStrBlobPtr& ConstStrBlobPtr::incr()
{
	check(curr, "increment past end of ConstStrBlobPtr");
	++curr;
	return *this;
}

ConstStrBlobPtr& ConstStrBlobPtr::operator++()
{
	check(curr, "increment past end of StrBlobPtr");
	++curr;
	return *this;
}

ConstStrBlobPtr& ConstStrBlobPtr::operator--()
{
	--curr;
	check(curr, "decrement past begin of StrBlobPtr");
	return *this;

}

ConstStrBlobPtr ConstStrBlobPtr::operator++(int)
{
	ConstStrBlobPtr ret = *this;
	++* this;
	return ret;
}

ConstStrBlobPtr ConstStrBlobPtr::operator--(int)
{
	ConstStrBlobPtr ret = *this;
	--* this;
	return ret;
}
StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il)) {}
StrBlob::StrBlob(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); }
StrBlob& StrBlob::operator=(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); return *this; }

void StrBlob::check(size_type i, const std::string& msg) const
{
	if (i >= data->size())
		throw std::out_of_range(msg);
}

std::string& StrBlob::front()
{
	check(0, "front on empty StrBlob");
	return data->front();
}

std::string& StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}

const std::string& StrBlob::front() const
{
	check(0, "front on empty StrBlob");
	return data->front();
}

const std::string& StrBlob::back() const
{
	check(0, "back on empty StrBlob");
	return data->back();
}

void StrBlob::pop_back()
{
	check(0, "pop_back on empty StrBlob");
	data->pop_back();
}

ConstStrBlobPtr StrBlob::begin() { return ConstStrBlobPtr(*this); }

ConstStrBlobPtr StrBlob::end()
{
	auto ret = ConstStrBlobPtr(*this, data->size());
	return ret;
}

bool operator==(const StrBlob& lhs, const StrBlob& rhs)
{
	return *lhs.data == *rhs.data;
}

bool operator!=(const StrBlob& lhs, const StrBlob& rhs)
{
	return !(lhs == rhs);
}
bool operator<(const StrBlob& lhs, const StrBlob& rhs)
{
	return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());
}

bool operator>(const StrBlob& lhs, const StrBlob& rhs)
{
	return rhs < lhs;
}

bool operator<=(const StrBlob& lhs, const StrBlob& rhs)
{
	return !(rhs < lhs);
}

bool operator>=(const StrBlob& lhs, const StrBlob& rhs)
{
	return !(lhs < rhs);
}


bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
	auto lret = lhs.wptr.lock(), rret = rhs.wptr.lock();
	return lret == rret && lhs.curr == rhs.curr;
}
bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
	return !(lhs == rhs);
}
int main()
{
	StrBlob b1 = { "a","aa","aaa" };
	StrBlob b2 = b1;
	return 0;
}

14.32

class Myclass
{
public:
	std::string * operator->()const 
	{
	return ptr->operator->();
}
private:
	StrBlobPtr *ptr;
};

14.34

#include<iostream>
#include<string>

class if_then_else
{
public:
	std::string operator()(bool b, std::string first_result, std::string second_result)
	{
		return b ? first_result : second_result;
	}
};

int main()
{
	if_then_else if_object;
	std::cout << if_object(true, "a", "b") << std::endl;
	return 0;
}

14.35

#include<iostream>
#include<string>
#include<vector>

using std::string;

class ReadString
{
public:
	ReadString(std::istream& i = std::cin) :is(i) {}
	string operator()()
	{
		std::string s;
		std::getline(is, s);
		return s;
	}

private:
	std::istream& is;

};

int main()
{

	std::vector<string>vs;
	string new_string;
	ReadString ReadObject;
	do
	{
		new_string = ReadObject();
		vs.push_back(new_string);

	} while (!new_string.empty());
	for (auto s : vs)
		std::cout << s << " ";
	std::cout << std::endl;
	return 0;
}

14.37

#include<string>
#include<iostream>
#include<vector>
#include<algorithm>

class equal_int
{
public:
	equal_int(int i) :default_number(i) {}
	bool operator()(int ele) { return default_number ==ele; }
private:
	int default_number;
};

int main()
{
	std::vector<int >vi = { 1,2,3,4,5,6 };
	std::replace_if(vi.begin(), vi.end(), equal_int(3), 5);
	for (auto i : vi)
		std::cout << i << " ";
	std::cout << std::endl;
	return 0;
}

14.38

#include<iostream>
#include<fstream>
#include<vector>
#include<string>

class CompareString
{

public:
	CompareString(size_t n) :default_size(n) {}
	bool operator()(const std::string& s)const
	{
		return default_size == s.size();
	}
private:
	size_t default_size;
};

int main()
{
	std::ifstream ifs("letter.txt");
	if (!ifs) return -1;
	std::vector<std::string>vs;
	for (std::string curr; ifs >> curr; vs.push_back(curr));

	for (int i = 1, n = 0; i < 11; ++i)
	{
		for (auto iter = vs.begin(); iter != vs.end();)
		{
			iter = std::find_if(iter + 1, vs.end(), CompareString(i));
			if (iter != vs.end())++n;
		}
		std::cout << "length:" << i << " " << n << std::endl;
		n = 0;
	}
	return 0;

}

14.39

#include<iostream>
#include<fstream>
#include<vector>
#include<string>

class CompareString
{

public:
	CompareString(size_t n) :default_size(n) {}
	bool operator()(const std::string& s)const
	{
		return default_size == s.size();
	}
private:
	size_t default_size;
};

int main()
{
	std::ifstream ifs("letter.txt");
	if (!ifs) return -1;
	std::vector<std::string>vs;
	for (std::string curr; ifs >> curr; vs.push_back(curr));

	int n = 0;
	for (int i = 1; i < 10; ++i)
	{
		for (auto iter = vs.begin(); iter != vs.end();)
		{
			iter = std::find_if(iter + 1, vs.end(), CompareString(i));
			if (iter != vs.end())++n;
		}
		
		
	}
	std::cout << "length 1-9:" << " " << n << std::endl;

	n = 0;
	for (int i = 10; i < 100; ++i)
	{
		for (auto iter = vs.begin(); iter != vs.end();)
		{
			iter = std::find_if(iter + 1, vs.end(), CompareString(i));
			if (iter != vs.end())++n;
		}

	}
	std::cout << "length 10-99:" << " " << n << std::endl;
	return 0;

}

14.40

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;

class bigger
{
public:
	bigger(vector<string>::size_type i) :default_num(i) {}
	bool operator()(const string& s)
	{
		return s.size() >= default_num;
	}

private:
	vector<string>::size_type default_num;

};

class str_compare
{
public:
	bool operator()(const string& lhs, const string& rhs)
	{
		return lhs.size() < rhs.size();
	}
};

vector<string>& elimDups(vector<string>& words)
{
	sort(words.begin(), words.end());
	auto end_unique = unique(words.begin(), words.end());
	words.erase(end_unique, words.end());
	return words;
}

void biggies(vector<string>& words, vector<string>::size_type sz)
{
	elimDups(words);
	stable_sort(words.begin(), words.end(), str_compare());
	auto wc = find_if(words.begin(), words.end(), bigger(sz));
	auto count = words.end() - wc;
	cout << count << endl;
	for (auto s : words)
		cout << s << " ";
	cout << endl;
}

int main()
{
	vector<string>vs = { "b","a","c","a","b","d","asdasdas","sa","sadsafsaf" };
	biggies(vs, 5);
	return 0;

}

14.41

当函数使用次数少且实现简单时,使用lambda;

14.42

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<functional>

int main()
{
	std::vector<int >v1 = { 1,1024,1025,1,1026 };
	std::cout << std::count_if(v1.begin(), v1.end(), std::bind(std::greater<int>(), std::placeholders::_1, 1024)) << std::endl;

	std::vector<std::string>vs = { "pooh","hi","hello" };
	std::cout << *(std::find_if(vs.begin(), vs.end(), std::bind(std::not_equal_to<std::string>(), std::placeholders::_1, "pooh"))) << std::endl;
	
	std::vector<int>v2 = { 1,2,3,4,5 };
	std::transform(v2.begin(), v2.end(),v1.begin(), std::bind(std::multiplies<int>(), std::placeholders::_1, 2));
	for (const auto i : v1)
		std::cout << i << " ";
	std::cout << std::endl;
	return 0;
}

14.43

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<functional>

int main()
{
	std::vector<int >v1 = { 2,3,5 };
	int v2 = 30;
	std::string ret = (std::count_if(v1.begin(), v1.end(), std::bind(std::modulus<int>(), std::placeholders::_1, v2))) 
		== v1.size() ? "divided" : "not ";
	std::cout << ret << std::endl;
	return 0;
}

14.44

#include <string>
#include <iostream>
#include <algorithm>
#include <map>
#include<functional>

int add(int i, int j) { return i + j; }
auto mod = [](int i, int j) { return i % j; };
struct divide
{
	int operator()(int dividend, int divisor)
	{
		return dividend / divisor;
	}
};

int main()
{

	
	std::map<std::string, std::function<int(int, int)>> binops = {
		{"+", add}, //函数指针
		{"-", std::minus<int>()},  //标准库函数对象
		{"/", divide()}, //用户自定义函数对象
		{"*", [](int i, int j) { return i * j; }}, //未命名lambda
		{"%", mod} //命名的lambda对象
	};

	std::cout << binops["+"](10, 5) << std::endl;
	std::cout << binops["-"](10, 5) << std::endl;
	std::cout << binops["*"](10, 5) << std::endl;
	std::cout << binops["/"](10, 5) << std::endl;
	std::cout << binops["%"](10, 5) << std::endl;

	return 0;
}

14.53

#include <cstddef>

class SmallInt
{
	friend SmallInt operator+(const SmallInt& si1, const SmallInt& si2) { SmallInt si_sum(si1.val + si2.val); return si_sum; }
public:
	SmallInt(int i = 0) : val(i) {}
	operator int() const { return val; }
private:
	std::size_t val;
};

int main()
{
	SmallInt s1;
	 //double d = s1 + 3.14;
	double d1 = s1 + SmallInt(3.14); //重载+
	double d2 = s1.operator int() + 3.14; //内置+

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值