【第十八章】C++ Primer plus 的编程练习题

/***********************************
	2017年12月28日13:59:12
	Athor:xiyuan255
	Course:C++
	Contain:pe18-1.cpp
	Reference: C++ Primer plus
		知识点:初始化列表模板类的应用
			1.初始化列表模板类:如果没有强制指定模板参数类型,则可以根据
			  初始化列表包的元素类型,作为制定的模板参数类型。但要求参数
			  列表包中的元素类型要一致才可以。
			2.初始化列表模板类:如果强制指定了模板参数类型,则会将初始化
			  列表包中的元素都转换为指定的模板参数类型。
	说明:C++ Primer plus第十八章的第一题练习题
	     【 参考 P838 】
*************************************/
// pe18-1.cpp -- uisng template initializer_list
#include <iostream>
#include <initializer_list>

template <typename T>  // C++11可以带类型默认值 typename T = double
T average_list(std::initializer_list<T> il)
{
	T sum = 0;
	for (auto p = il.begin(); p != il.end(); p++) 
		sum += (*p);

	return (il.size() == 0 ? sum : sum / il.size());
}

int main()
{
    using namespace std;	
// list of double deduced from list constents
	auto q = average_list({15.4, 10.7, 9.0}); // T = double
	cout << q << endl;
// list of int deduced from list constents
	cout << average_list({20, 30, 19, 17, 45, 38}) << endl;  // T = int
// forced list of double
	auto ad = average_list<double>({'A', 70, 65.33});
	cout << ad << endl;

	return 0;
}

/**
输出结果:
	11.7
	28
	66.7767
*/

// cpmv.h -- class Cpmv decalaration
#ifndef __CPMV_H__
#define __CPMV_H__
#include <iostream>
#include <string>

class Cpmv
{
public:
	struct Info
	{
		std::string qcode;
		std::string zcode;
	};
private:
	Info *pi;
public:
	Cpmv();
	Cpmv(std::string q, std::string z);
	Cpmv(const Cpmv & cp); // 复制构造函数
	Cpmv(Cpmv && mv);      // 移动构造函数
	~Cpmv();
	Cpmv & operator=(const Cpmv & cp); // 复制赋值运算符操作
	Cpmv & operator=(Cpmv && cp);      // 移动赋值运算符操作
	Cpmv operator+(const Cpmv & obj) const;
	void Display() const;
};

#endif /* __CPMV_H__ */

// cpmv.cpp -- class Cpmv methods definition
#include "cpmv.h"


// Cpmv class methods
Cpmv::Cpmv()
{
	pi = nullptr;
	std::cout << "default constructor called.\n";
}

Cpmv::Cpmv(std::string q, std::string z)
{
	pi = new Info;
	pi->qcode = q;
	pi->zcode = z;
	std::cout << "string, string constructor called.\n";
}

Cpmv::Cpmv(const Cpmv & cp)
{
	pi = new Info;
	pi->qcode = cp.pi->qcode;
	pi->zcode = cp.pi->zcode;
	std::cout << "copy constructor called.\n";
}

Cpmv::Cpmv(Cpmv && mv)
{
	pi = mv.pi;
	mv.pi = nullptr;
	std::cout << "move constructor called.\n";
}

Cpmv::~Cpmv()
{
	delete pi;
	std::cout << "destructor called.\n";
}

Cpmv & Cpmv::operator=(const Cpmv & cp)
{
	if (this == &cp)
		return *this;
	pi = new Info;
	pi->qcode = cp.pi->qcode;
	pi->zcode = cp.pi->zcode;
	std::cout << "copy assignment operator called.\n";
	return *this;
}

Cpmv & Cpmv::operator=(Cpmv && cp)
{
	if (this == &cp)
		return *this;
	pi = cp.pi;
	cp.pi = nullptr;
	std::cout << "move assignment operator called.\n";
	return *this;
}

Cpmv Cpmv::operator+(const Cpmv & obj) const
{
	Cpmv temp; // 会调用默认构造函数创建一个对象
	temp.pi = new Info;
	temp.pi->qcode = pi->qcode + obj.pi->qcode;
	temp.pi->zcode = pi->zcode + obj.pi->zcode;

	std::cout << "add assignment operator called.\n";
	return temp; // return 返回的类型不是引用类型,所以因为的右值
	       // 首选调用移动构造函数将temp对象移动到函数的返回值的内
	       // 存空间中
}

void Cpmv::Display() const
{
	std::cout << "pi->qcode: " << pi->qcode << std::endl;
	std::cout << "pi->zcode: " << pi->zcode << std::endl;
}

/***********************************
	2017年12月29日09:13:41
	Athor:xiyuan255
	Course:C++
	Contain:pe18-2.cpp
	Reference: C++ Primer plus
		知识点:
		1.一般而言,将左值传递给const左值引用参数时,参数将被初始化为
		  左值。将右值传递给函数时,const左值引用参数将指向右值的临时
		  拷贝。
		2.一般而言,将左值传递给非const左值引用参数时,参数将被初始化
		  为左值。但非const左值引用参数不能接受右值实参。
		3.总之,非const左值形参与左值实参匹配,非const右值形参与右值实
		  参匹配;const左值形参可与左值或右值实参匹配,但编译器优先选择
		  前两种方式(如果可供选择的话)。
	说明:C++ Primer plus第十八章的第二题练习题
		 【 参考 P838 】
*************************************/
// pe18-2.cpp -- using class Cpmv
#include <iostream>
#include "cpmv.h"

int main()
{
	/* Cpmv("112233", "445566")调用Cpmv(string q, string z)
	 * 构造函数创建一个临时对象,它属于一个右值,因在定义时
	 * 用'=',则首选调用Cpmv(Cpmv && mv)移动构造函数将临时
	 * 对象赋给cpmv1对象。 */
	Cpmv cpmv1 = Cpmv("112233", "445566");
	Cpmv cpmv2("1234", "5678");
	Cpmv cpmv3 = cpmv1;
	Cpmv cpmv4;
	cpmv4 = cpmv2;
	std::cout << "cpmv1 contents:\n";
	cpmv1.Display();
	std::cout << "cpmv2 contents:\n";
	cpmv2.Display();
	std::cout << "cpmv3 contents:\n";
	cpmv3.Display();
	std::cout << "cpmv4 contents:\n";
	cpmv4.Display();

	Cpmv cpmv5;
	/* cpmv3 + cpmv4首先调用cpmv3.operator+(cpmv4)创建一个临时
	 * 对象,它是一个右值(return返回temp对象右值),然后调用
	 * cpmv5.operator=(cpmv3 + cpmv4的返回值)移动赋值运算符。*/
	cpmv5 = cpmv3 + cpmv4;
	std::cout << "cpmv5 contents:\n";
	cpmv5.Display();

	return 0;
}

/**
输出结果:
	string, string constructor called.
	move constructor called.
	destructor called.
	string, string constructor called.
	copy constructor called.
	default constructor called.
	copy assignment operator called.
	cpmv1 contents:
	pi->qcode: 112233
	pi->zcode: 445566
	cpmv2 contents:
	pi->qcode: 1234
	pi->zcode: 5678
	cpmv3 contents:
	pi->qcode: 112233
	pi->zcode: 445566
	cpmv4 contents:
	pi->qcode: 1234
	pi->zcode: 5678
	default constructor called.
	default constructor called.
	add assignment operator called.
	move constructor called.
	destructor called.
	move assignment operator called.
	destructor called.
	cpmv5 contents:
	pi->qcode: 1122331234
	pi->zcode: 4455665678
	destructor called.
	destructor called.
	destructor called.
	destructor called.
	destructor called.
*/

/***********************************
	2017年12月29日09:43:41
	Athor:xiyuan255
	Course:C++
	Contain:pe18-3.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十八章的第三题练习题
	     【 参考 P838 】
*************************************/
// pe18-3.cpp -- test sum_value() function
#include <iostream>

long double sum_value()  // 该函数不会调用
{
	return 0;
}

template <typename T>
long double sum_value(const T & value)
{
	return value;
}

// 可变参数模板(variadic template)
template <typename T, typename... Args>  // Args is a template parameter pack
long double sum_value(const T & value, const Args&... args) // args is a function parameter pack
{ // T使用的类型和Args要一致,如本例中T是const &类型,Args也是。
  // 因为T对应的value值就是每次从参数包args取出一个赋给它的,
  // 所以要类型一致,每次取出一个,直到参数包args取出最后一个
  // 则调用long double sum_value(const T & value)函数结束递归。
	return value + sum_value(args...);
}

int main()
{
	long double sum = sum_value(1, 2, 3, 4, 5, 6, 7, 8, 9);
	std::cout << "sum = " << sum << std::endl;

	return 0;
}

/**
输出结果:
	sum = 45
*/

/***********************************
	2017年12月29日10:19:01
	Athor:xiyuan255
	Course:C++
	Contain:pe18-4.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十八章的第四题练习题
		 【 参考 P838 】
*************************************/
// pe18-4.cpp -- using a lambda handler functor
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>

template<class T>  // functor class defines operator()()
class TooBig
{
private:
	T cutoff;
public:
	TooBig(const T & t) : cutoff(t) { }
	bool operator()(const T & v) { return v > cutoff; }
};

//void outint(int n) { std::cout << n << " "; }
auto outint = [](int n) { std::cout << n << " "; }; // lambda 

int main()
{
	using std::list;
	using std::cout;
	using std::endl;

	TooBig<int> f100(100);  // limit = 100
	int vals[10] = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
	list<int> yadayada(vals, vals + 10); // range constructor
	list<int> etcetera(vals, vals + 10);
// C++11 can use the following instead
//	list<int> yadayada = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
//	list<int> etcetera = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
	cout << "Original lists:\n";
	for_each(yadayada.begin(), yadayada.end(), outint);
	cout << endl;
	for_each(etcetera.begin(), etcetera.end(), outint);
	cout << endl;

	/* f100类似函数指针,其实调用的是f100(const T & v) 
	 * 即调用f100.operator(v)运算符操作函数,remove_if
	 * 函数的作用是,将yadayada对象的每个元素依次取出
	 * 发送给f100.operator(v),如果该函数返回true则移除
	 * yadayada对象中的该元素,否则不做处理。 */
	yadayada.remove_if([](int n){ return n > 100; });             // use a named function object
	etcetera.remove_if([](int n){ return n > 200; }); // constuct a function object
	cout << "Trimmed lists:\n";
	for_each(yadayada.begin(), yadayada.end(), outint);
	cout << endl;
	for_each(etcetera.begin(), etcetera.end(), outint);
	cout << endl;

	return 0;
}

/**
输出结果:
	Original lists:
	50 100 90 180 60 210 415 88 188 201
	50 100 90 180 60 210 415 88 188 201
	Trimmed lists:
	50 100 90 60 88
	50 100 90 180 60 88 188
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值