[2018年5月7号]C++ primer 课后练习 第十二章 动态内存 第十三章 拷贝控制

12.32

class QueryResult;
using line_no = vector<string >::size_type;

class TextQuery {
public:
    TextQuery(ifstream&);
    QueryResult query(const string &)const;
private:
    StrBlob file;
    map<string, shared_ptr<set<line_no>>> wm;
};

TextQuery::TextQuery(ifstream & ifs):file(StrBlob()){
    string lineStr, word;
    while (getline(ifs, lineStr))
    {
        file.push_back(lineStr);
        int lineCount = file.size();
        istringstream ist(lineStr);
        while (ist >> word)
        {
            shared_ptr<set<line_no>>& line = wm[word];
            if(!line){
                line.reset(new set<line_no>);
            }
            line->insert(lineCount);
        }
    }
}

class QueryResult {
friend ostream& print(ostream&, const QueryResult& );
public:
    QueryResult(string s, shared_ptr<set<line_no>> ss, StrBlob sp):s(s),ss(ss),sp(sp){};
private:
    string s;
    shared_ptr<set<line_no>> ss;
    StrBlob sp;
};

QueryResult TextQuery::query(const string & word)const{
    static shared_ptr<set<line_no>> noData(new set<line_no>);
    auto result = wm.find(word);
    if(result == wm.end()){
        return QueryResult(word, noData, file);
    }else{
        return QueryResult(word, wm.find(word)->second, file);
    }
}

ostream& print(ostream& os, const QueryResult & ptr){
    cout << "you find " << ptr.ss->size() << " in file" << endl;
    ConstStrBlobPtr sbp(ptr.sp);
    for (size_t i = 0; i < ptr.sp.size(); i++, sbp.incr())
    {
        set<line_no>::iterator haveLine= ptr.ss->find(i);
        if(haveLine!= ptr.ss->end()){
            cout << sbp.deref() << endl;
        }
    }
    return os;
}

12.33

class QueryResult {
friend ostream& print(ostream&, const QueryResult& );
public:
    QueryResult(string s, shared_ptr<set<line_no>> ss, shared_ptr<vector<string>> sp):s(s),ss(ss),sp(sp){};
    set<line_no>::iterator& begin() { return ss->begin(); }
    set<line_no>::iterator& end() { return ss->end(); }
    shared_ptr<vector<string>>& get_file() { return sp; }
private:
    string s;
    shared_ptr<set<line_no>> ss;
    shared_ptr<vector<string>> sp;
};

13.1:

如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数

在用=定义变量时会发生

将一个对象作为实参传递给一个非引用类型的形参

从一个返回类型为非引用类型的函数返回一个对象

用花括号列表初始化一个数组中的元素或一个聚合类中的成员

13.2

在函数调用过程中,具有非引用类型的参数要进行拷贝初始化,类似的,当一个函数具有非引用的返回类形时,返回值会被用来初始化调用方的结果

拷贝构造函数被用来初始化非引用类类型参数,这一特性解释了为什么拷贝函数自己的参数必须是引用类形,如果其参数不是引用类型,则调用永远也不会成功--为了调用拷贝构造函数,我们必须拷贝它的实参,但为了拷贝实参,我们又需要调用拷贝构造函数,如此无限循环

13.3

按照参数列表,依次调用成员变量的拷贝构造函数

13.4

Point global;
Point foo_bar(Point arg){
    Point local = arg, *heap = new Point(global);
    *heap = local;
    Point pa[4] = {local, *heap};
    return *heap;
} 共6次

13.5

class HasPtr {
public:
    HasPtr(const std::string &s = std::string()):
        ps(new std::string(s)),i(0){}
    HasPtr(const HasPtr& has): ps(new std::string(*has.ps)),i(has.i){}
private:
    std::string *ps;
    int i;
};

13.6

拷贝赋值运算符会将右侧运算对象的每个非static成员赋予左侧运算对象的对应成员,当=两侧为相同类类型时候会使用,当一个类未定义自己的拷贝赋值运算符,编译器会为它生成一个

13.7

将右侧的strblob的非static成员依次调用拷贝赋值函数给左侧的strblob变量

13.8

    HasPtr& operator = (HasPtr& has){
        ps = new string(*has.ps);
        i = has.i;
    }

拷贝时需要动态内存重新声请一块string内存,不然两个对象会同时指向一个string,导致空悬指针产生

13.9

析构函数执行与构造函数相反的操作,构造函数初始化对象的非static数据成员,还可能做一些其他工作;析构函数 释放对象使用的资源,并销毁对象的非static数据成员,当一个类未定义自己的析构函数时,编译器会为它定义一个合成析构函数

13.10

strblob成员变量会依次调用自己的析构函数来销毁自己

13.11

    ~HasPtr(){}

13.12

3次

形参传入的accum,和局部变量item1,item2

13.13


13.14 

猜测,输出同样的值

13.15

会改变,除了a,b和c都是调用的拷贝构造函数,会生成与a不同的序号,f函数调用的时候也会执行拷贝构造函数

13.16

会改变,但f函数调用时候使用的引用,所以输出的值会比使用形参小一号

13.17

13.14测试结果


13.15测试结果

13.16测试结果

与猜测相同

进一步验证





13.18

 
 

static int number = 0;

class Employee{

public: Employee():no(number){ number ++;}; Employee(string name) :name(name),no(number) { number++; }private: string name; int no;};

13.19

需要,每位雇员都需要一个自己的雇员证号,在使用默认拷贝构造函数时候不会增加雇员证号,会出现重复的号码

    Employee(const Employee& emp) :name(emp.name), no(number) { number++; }

13.20

调用其默认的拷贝构造参数,拷贝赋值运算符,析构函数,

13.21

需要,否则经过拷贝构造函数和拷贝赋值运算符生成TextQuery和QueryResult的成员会指向同一片内存,虽然有智能指针不会导致delete出现问题,但是在操作时候会和原先设想不符

    TextQuery(const TextQuery& tq):file(new vector<string>(tq.file->begin(), tq.file->end())){
        for(auto it : tq.wm){
            wm[it.first].reset(new set<line_no>(it.second->begin(), it.second->end()));
        }
    } ;

QueryResult(const QueryResult& qr):s(qr.s),ss(new set<line_no>(qr.ss->cbegin(), qr.ss->cend())), sp(new vector<string>(qr.sp->cbegin(), qr.sp->cend())){}

默认拷贝构造函数


自定义拷贝构造函数后


13.22

    HasPtr& operator = (HasPtr& has){
        ps = new string(*has.ps);
        i = has.i;
        return *this;
    }
    HasPtr(const HasPtr& has) : ps(new std::string(*has.ps)), i(has.i) {} 

值拷贝如上

13.23


没考虑到会销毁运算符左侧资源,验证后,的确发生了内存泄露

13.24

如果未定义析构函数,在变量退出作用域时候,申请的内存不被释放,将导致内存泄露



如果未定义拷贝构造函数会导致a和b的成员指针都指向同一块内存,当其中变量退出作用域时,会释放该区域导致另一个变量内的成员指针变成空悬指针

13.25

因为StrBlob的data是用智能指针定义的,会自动释放,所以不需要析构函数

13.26

    StrBlob& operator=(StrBlob& str){
        data = make_shared<vector<string>>(*str.data);
        return *this;
    }
    StrBlob(StrBlob& str): data(make_shared<vector<string>>(*str.data)){}

13.27

    HasPtr(const HasPtr& has) : ps(has.ps), i(has.i), use_count(has.use_count){ ++*use_count; }
    HasPtr(const std::string &s = std::string()):
        ps(new std::string(s)),i(0){}
    ~HasPtr() {
        if(--*use_count == 0){
            delete ps;
            delete use_count;
        }
    }

13.28

class TreeNode {
    TreeNode() :left(0), right(0) {}
    TreeNode(const TreeNode& tn) :value(tn.value), count(tn.count),left(tn.left), right(tn.right) {}
    TreeNode& operator=(TreeNode& tn){
        value = tn.value;
        count = tn.count;
        left = tn.left;
        right= tn.right;
        return *this;
    }

private:
    string value;
    int count;
    TreeNode *left;
    TreeNode *right;

};


class BinStrTree {
public:
    BinStrTree():root(0){}
    BinStrTree(const BinStrTree& bst):root(bst.root){}
    BinStrTree& operator=(BinStrTree& bst){
        root = bst.root;
        return *this;
    }
private:
    TreeNode * root;
};

猜你喜欢

转载自blog.csdn.net/qq_22478401/article/details/80220862