C++ Primer 第13章答案

习题13.1
(1)如果一个函数的一个参数是自身类型的引用,且任何额外参数都有默认值,
那么它就是拷贝构造函数。
(2)以下三种对象需要调用该函数
一个对象作为函数参数,以值传递的方式传入函数体
一个对象作为函数返回值,以值传递的方式从函数返回
一个对象用于给另一个对象进行初始化的时候。

习题13.2
参数应该是Sales_data&类型

习题13.3
当我们拷贝StrBlor时,shared_ptr成员use_cout增加了一个
而拷贝StrBlobPtrs, weak_ptr成员use_cout并没有改变

习题13.4
Point global;
Point foo_bar(Point arg) // 传参拷贝1
{
    Point local = arg, *heap = new Point(global); // 2, 3
    *heap = local;
    Point pa[ 4 ] = { local, *heap }; // 4, 5
    return *heap; // 6
}

习题13.5
HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) {}

习题13.6
(1)拷贝赋值运算符 =
(2)当赋值运算发生的时候
(3)完成一些拷贝操作
(4)如果一个类没有定义的时候

习题13.7
赋值StrBlob,会拷贝出一个新的StrBlob。
拷贝StrBlobPtr,会将指针内容赋值给另一个StrBlobPtr,并不会产生新的对象

习题13.8
HasPtr& operator=(const HasPtr& hp)
{
    std::string* new_ps = new std::string(*hp.ps);
    delete ps;
    ps = new_ps;
    i = hp.i;
    return *this;
}

习题13.9
析构函数释放对象所使用的资源;
析构函数首先执行函数体,然后销毁成员;
在类没有定义析构函数的时候生成。

习题13.10
当一个StrBlob对象销毁时,它会删除string* ps及int i,及它所使用的资源;
StrBlobPtr销毁,其所指向的对象不会被销毁。

习题13.11
~HasPtr(){delete ps;}//释放动态分配的内存。

习题13.12
3次

习题13.13
struct X {
    X() { std::cout << "X()" << std::endl; }
    X(const X& obj) : i(obj.i),j(new int()){ std::cout << "X(const X&)" << std::endl; }
    X& operator=(const X& obj)
    {
        i = obj.i;
        auto ptr = new int();
        delete j;
        j = ptr;
                                return *this;
    }
    ~X() { delete j; }
    int i;
    int* j;
};

习题13.14
三个数字相同

习题13.15
会,三个数字会不同
在函数传参时,这时应该使用的的是拷贝构造函数而非默认构造函数

习题13.16
会,输出回合传进来的引用相同。

习题13.17
#include

class numbered {
public:
    static int unique;
    numbered()
    {    
        mysn = ++unique;
    }
    numbered(numbered&)
    {
        mysn = ++unique;
    }
    int mysn;
};
int numbered::unique = 0;


void f(const numbered& s)
{
    std::cout << s.mysn << std::endl;
}

int main()
{
    numbered a, b = a, c = b;//a使用默认构造,b,c使用拷贝构造
    f(a); // 拷贝构造
    f(b); // 拷贝构造
    f(c); // 拷贝构造
    system("pause");
    return 0;
}
在未定义拷贝构造函数时,我们使用的是默认拷贝构造函数,默认拷贝构造函数并没有自增操作。

习题3.18
.h
#include
using std::string;

class Employee {
public:
    Employee();
    Employee(const string& name);
    const int id() const { return id_; }

private:
    string name_;
    int id_;
    static int s_increment;
};

.c
int Employee::s_increment = 0;

Employee::Employee()
{
    id_ = s_increment++;
}

Employee::Employee(const string& name)
{
    id_ = s_increment++;
    name_ = name;
}

习题13.19
需要,每个人都是不同的

习题13.20
它的成员(例如指针和容器)将会被拷贝/销毁

习题13.21
需要,TextQuery,会自行分配一个vector的内存。而另一个不需要

习题13.22
略,前面写过

习题13.23
需要删除原有的资源,再进行拷贝。

习题13.24
使用合成的默认析构/构造函数

习题13.25
拷贝构造函数,类的行为像指针,并不会为指针分配新的内存,而是拷贝内存
地址,因为它是weak_ptr,不进入智能指针的计数,因此不需要delete或者reset

习题13.26

习题13.27
class HasPtr {
public:
    HasPtr(const std::string& s = std::string())
        : ps(new std::string(s)), i(0), use(new size_t(1))
    {
    }
    HasPtr(const HasPtr& hp) : ps(hp.ps), i(hp.i), use(hp.use) { ++*use; }
    HasPtr& operator=(const HasPtr& rhs)
    {
        ++*rhs.use;
        if (--*use == 0) {
            delete ps;
            delete use;
        }
        ps = rhs.ps;
        i = rhs.i;
        use = rhs.use;
        return *this;
    }
    ~HasPtr()
    {
        if (--*use == 0) {
            delete ps;
            delete use;
        }
    }

private:
    std::string* ps;
    int i;
    size_t* use;
};

习题13.29
调用的swap是不在同一命名空间的。

习题13.30
void swap(HasPtr& lhs, HasPtr& rhs)
{
    using std::swap;
    swap(lhs.ps, rhs.ps);
    swap(lhs.i, rhs.i);
    std::cout << "call swap(HasPtr& lhs, HasPtr& rhs)" << std::endl;
}

习题13.31
bool operator<(const HasPtr& lhs, const HasPtr& rhs)
{
    return *lhs.ps < *rhs.ps;
}

习题13.32
得益于它在交换时,不需要额外的内存开销。
 

 

后面的类都分文件写在工程里了,有点懒,不想复制了。。。

 

后来再开一篇关于右值引用和move的博客,这个用不好很容易down掉,所以基本我见过的工程大多都是拷贝而不是move。

但是这个优化真的令人眼馋,如果用好可以提升一些性能,用不好。。。那就,到处找bug。。。

你可能感兴趣的:(C++)