C++ Primer Plus章节编程练习第十八章

1

题目

  下面是一个简短程序的一部分:

int main(){
    using namespace std;
    auto q=average_list({15.4,10.7,9.0});
    cout<<q<<endl;
    cout<<average_list({20,30,19,17,45,38})<<endl;
    auto ad=average_list<double>({'A',70,65.33});
    cout<<ad<<endl;
    return 0;
}

  请提供函数average_list(),让该程序变得完整。它应该是一个模板函数,其中的类型参数指定了用作函数参数的initilize_list 模板的类型以及函数的返回类型。

题解

#include<iostream>
#include<vector>
#include<initializer_list>
template<typename T>
T average_list(std::initializer_list<T> values){
    T average=0;
    for(auto item:values) average+=item;
    return values.size()==0?0:average/values.size();
}
int main(){
    using namespace std;
    auto q=average_list({15.4,10.7,9.0});
    cout<<q<<endl;
    cout<<average_list({20,30,19,17,45,38})<<endl;
    auto ad=average_list<double>({'A',70,65.33});
    cout<<ad<<endl;
    return 0;
}

2

题目

  下面是类Cpmv的声明:

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&&mv);
    Cpmv operator+(const Cpmv& obj)const;
    void Display()const;
};

  函数operator+()应创建一个对象,其成员qcode和zcode有操作数的相应成员拼接而成。请提供为移动构造函数和移动赋值运算符实现移动语义的代码。编写一个使用所有这些方法的程序。为方便测试,让各个方法都显示特定的内容,以便知道它们被调用。

题解

#include<iostream>
#include<string>
using namespace std;
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&&mv);
    Cpmv operator+(const Cpmv& obj)const;
    void Display()const;
};
Cpmv::Cpmv(){
    pi=new Info;
    cout<<"Default Constructor called!"<<endl;
}
Cpmv::Cpmv(std::string q, std::string z){
    pi=new Info;
    pi->qcode=q;
    pi->zcode=z;
    cout<<"String Constructor called!"<<endl;
}
Cpmv::Cpmv(const Cpmv& cp){
    pi=new Info;
    pi->qcode=cp.pi->qcode;
    pi->zcode=cp.pi->zcode;
    cout<<"Copy Constructor called!"<<endl;
}
Cpmv::Cpmv(Cpmv&& cp){
    pi=cp.pi;
    cp.pi=nullptr;
    cout<<"Move Constructor called!"<<endl;
}
Cpmv::~Cpmv(){
    delete pi;
    cout<<"Destrutor called!"<<endl;
}
Cpmv& Cpmv::operator=(const Cpmv&cp){
    if(this==&cp) return *this;
    pi=new Info;
    pi->qcode=cp.pi->qcode;
    pi->zcode=cp.pi->zcode;
    cout<<"Assignment called!"<<endl;
    return *this;
}
Cpmv& Cpmv::operator=(Cpmv&&mv){
    pi=mv.pi;
    mv.pi=nullptr;
    cout<<"Move Assignment called!"<<endl;
    return *this;
}
Cpmv Cpmv::operator+(const Cpmv& obj)const{
    string qcode=pi->qcode+obj.pi->qcode;
    string zcode=pi->zcode+obj.pi->zcode;
    cout<<"Operator+() called!"<<endl;
    return Cpmv(qcode,zcode);
}
void Cpmv::Display()const{
    cout<<"Display called!"<<endl;
    cout<<"Qcode: "<<pi->qcode<<endl;
    cout<<"Zcode: "<<pi->zcode<<endl;
}
int main(){
    using namespace std;
    Cpmv one;                   //默认构造函数
    Cpmv two("qcode","zcode");  //传参构造函数
    Cpmv three(two);            //复制构造函数
    Cpmv four(move(three+two)); //移动构造函数 ,其中调用了重载的+运算符,传参构造函数和析构函数
    Cpmv five;                  //默认构造函数
    five=four;                  //赋值操作符
    Cpmv six;                   //默认构造函数
    six=move(five);             //移动赋值操作符
    six.Display();
    return 0;
}

3

题目

  编写并测试可变参数模板函数sum_value(),它接受任意长度的参数列表(其中包含数值,但可以是任何类型),并以long double的方式返回这些数值的和。

题解

#include<iostream>
// template<class T>
// long double sum_value(){return 0;}
template<class T>
long double sum_value(T value){return value;}
template<class T,class... Args>
long double sum_value(T value, Args... args){
    return value+sum_value(args...);
}
int main(){
    using namespace std;
    cout<<sum_value(1,2,3,4,5,6,7,8,9,10)<<endl;
    cout<<sum_value(100.00,3,20.99,4.6,3.6)<<endl;
    return 0;
}

4

题目

  使用lambda重新编写程序清单16.15。具体地说,使用一个有名称的lambda替换函数outint(),并将函数符替换为两个匿名lambda表达式。

题解

#include<iostream>
#include<list>
#include<iterator>
#include<algorithm>
template<class T>
class TooBig{
private:
    T cutoff;
public:
    TooBig(const T &t):cutoff(t){}
    bool operator()(const T &v){return v>cutoff;}
};
auto outint_lambda=[](int n){std::cout<<n<<std::endl;};
int main(){
    using namespace std;
    TooBig<int> f100(100);
    int vals[10]={50,100,90,180,60,210,415,88,188,201};
    list<int> yadayada(vals,vals+10);
    list<int> etcetera(vals,vals+10);
    cout<<"Original lists:\n";
    for_each(yadayada.begin(),yadayada.end(),outint_lambda);
    cout<<endl;
    yadayada.remove_if(f100);               //删除大于100的数字
    etcetera.remove_if(TooBig<int>(200));   //删除大于两百的数字
    cout<<"Trimmed lists:\n";
    for_each(yadayada.begin(),yadayada.end(),outint_lambda);
    cout<<endl;
    for_each(etcetera.begin(),etcetera.end(),outint_lambda);
    cout<<endl;
    return 0;
}
//由16.15改编

当珍惜每一片时光~