练习13.14:
这是一个典型的应该定义拷贝控制成员的场合。如果不定义拷贝构造函数和拷贝赋值运算符,依赖合成的版本,则在拷贝构造和赋值时,会简单复制数据成员。对本问题来说,就是将序号简单复制给新对象。
因此,代码中对a、b、c三个对象调用函数f,会输出三个相同的序号——合成拷贝构造函数被调用时简单复制序号,使得三个对象具有相同的序号。
练习13.15:
在此程序中,都是拷贝构造函数在起作用,因此定义能生成新的序号的拷贝构造函数会改变输出结果。
但注意,新的输出结果不是0、1、2,而是3、4、5。
因为在定义变量a时,默认构造函数起作用,将其序号设定为0。当定义b、c时,拷贝构造函数起作用,将它们的序号分别设定为1、2。
但是,在每次调用函数f时,由于参数是numbered类型,又会触发拷贝构造函数,使得每一次都将形参s的序号设定为新值,从而导致三次的输出结果是3、4、5。
练习13.16:
会改变输出结果,新结果是0、1、2。
原因是,将参数改为const numbered &。由于形参类型由类类型变为引用类型,传递的不是类对象而是类对象的引用。这意味着调用f时不再触发拷贝构造函数将实参拷贝给形参,而是传递实参的引用。因此,对每次调用,s都是指向实参的引用,序号自然就是实参的序号。而不是创建一个新的对象,获得一个新序号。
练习13.17:
#include <iostream>
using namespace std;class numbered {private:static int seq;public:numbered() {mysn = seq++;}numbered(numbered &n) {mysn = seq++;}int mysn;
};int numbered::seq = 0;void f(numbered s) {cout << s.mysn << endl;
}int main() {numbered a, b = a, c = b;f(a);f(b);f(c);return 0;
}
测试结果:
#include <iostream>
using namespace std;class numbered {private:static int seq;public:numbered() {mysn = seq++;}numbered(numbered &n) {mysn = seq++;}int mysn;
};int numbered::seq = 0;void f(const numbered &s) {cout << s.mysn << endl;
}int main() {numbered a, b = a, c = b;f(a);f(b);f(c);return 0;
}
测试结果: