C++ Primer第五版 第十三章---练习题答案(学习笔记)

本文详细解释了C++中的拷贝构造函数和拷贝赋值运算符的工作原理,以及何时使用它们。讨论了StrBlob和StrBlobPtr在拷贝过程中的行为,以及为何某些声明非法。还涵盖了析构函数的作用和合成析构函数的工作方式。同时,提供了练习题解答,帮助读者深入理解这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

13.1 

拷贝构造函数是什么?什么时候使用它?

    符合 “ 第一个参数是自身类类型的引用,且任何额外参数都有默认值 ” 的 构造函数 是拷贝构造函数。

当:

    1.将一个对象作为实参传递给一个非引用类型形参 (调用实参作为非&参数)

    2.从一个返回类型为非引用类型函数返回一个对象 (f(x)返回非&类型)

    3.用花括号列表初始化一个数组中的元素或者一个聚合类中的成员 (列表初始化一个array或者聚合类成员)时。

13.2

解释为什么下面的声明是非法的:

Sales_data::Sales_data(Sales_data rhs);

    拷贝构造函数的第一个参数应该是自身类类型的引用,如果不是,则调用永远不可能成功——为了调用拷贝构造函数,我们必须拷贝它的实参,但为了拷贝实参,我们又需要调用拷贝构造函数,如此无限循环。

13.3

当我们拷贝一个StrBlob时,会发生什么?拷贝一个StrBlobPtr呢?

    StrBlob中元素复制,且智能指针计数加一。StrBlobStr中元素复制,弱指针复制不影响计数器

13.4

假定Point是一个类类型,他有一个Public的拷贝构造函数,指出下面程序片段中哪些地方使用了拷贝构造函数:

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

    foo_bar 的参数不是引用类型,需拷贝;使用拷贝构造函数,函数返回类型非引用,需拷贝;将arg拷贝到local、将global拷贝到heap,将local和*heap拷贝pa[4],需拷贝;local拷贝到*heap属于拷贝赋值运算符

13.5

给定下面的类框架,编写一个拷贝构造函数,拷贝所有成员。你的构造函数应该动态分配一个新的string(参见12.1.2节,第407页),并将对象拷贝到ps指向的位置,而不是拷贝ps本身:

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

13.6

拷贝赋值运算符是什么?什么时候使用它?合成拷贝赋值运算符完成什么工作?什么时候会生成合成拷贝赋值运算符?

    就是一个名为 operator= 的函数(operator后加表示要定义的运算符的符号),重载运算符,有返回类型和参数,返回类型通常是左侧运算符的引用;

    若在类内未显式定义,则编译器会自动生成合成拷贝赋值运算符,它主要是将运算符右侧的所有非static成员赋给左侧元算对象对应成员(或是用来禁止该类型对象的赋值)

13.7

当我们将一个StrBlob赋值给另一个StrBlob时,会发生什么?赋值StrBlobPtr呢?

    所有成员的赋值会发生,两个StrBlob中智能指针所指对象内存相同,计数器加一,两个StrBlobPtr中弱指针所致对象内存相同,计数器不变。

13.8

为13.1.1节(第443页)练习13.5中的HasPtr类编写赋值运算符。类似拷贝构造函数,你的赋值运算符应该将对象拷贝到ps指向的位置。

HasPtr& operator= (const HasPtr& HP)
{
    string *p = new string(*HP.ps);  //new返回的是指向分配好内存、创建了对象的指针
    dalete ps;  //首先删除原内存
    ps = p;  //赋值
    i = HP.i;
    return *this;  //返回值
}

13.9

析构函数是什么?合成析构函数完成什么工作?什么时候会生成合成析构函数?

    析构函数类的一个成员函数,名字由波浪号类名构成。它没有返回值,也不接受参数

    类似拷贝构造函数拷贝构造运算符,对于某些类,合成析构函数用来阻止该类型的对象被销毁。如果不是这种情况,合成析构函数的函数体为空

    当一个类未定义自己的析构函数时,编译器就会为它定义一个合成析构函数(synthesized destructor)。

13.10

当一个StrBlob对象销毁时会发生什么?一个StrBlobPtr对象销毁时呢?

    所有对象的数据成员被销毁,智能指针的计数减一,所有对象的数据成员被销毁,弱指针不影响计数器。

13.11

为前面练习中的HasPtr类添加一个析构函数。

    &:析构函数中,分配的动态内存对象,需要dalete。

~HasPtr() { dalete ps; }  //必须首先delete对象ps,ps指向一个动态分配的string

13.12

在下面的代码片段中会发生几次析构函数调用?

bool fcn(const Sales_data *trans, Sales_data accum)
{
    Sales_data item1(*trans),item2(accum);
    return item1.isbn() != item2.isbn;
}

    &:当指向一个对象引用或者指针离开作用域时,析构函数不执行

    所以,在本段代码中析构函数一共执行三次:accum,item1,item2 .

13.13 (未完成)

理解拷贝控制成员和构造函数的一个好方法是定义一个简单的类,为该类定义这些成员,每个成员都打印出自己的名字

str
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值