练习13.1
拷贝构造函数是什么?什么时候使用它?
解答:
在书中没有明确的给出定义,不过在使用过程中,已经能大致了解它的作用。
引用一下百度百科的定义:
【引用】拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其唯一的形参必须是引用,但并不限制为const,一般普遍的会加上const限制。此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。
在什么时候使用它,书中其实都有写,不过需要总结一下:
共有四种情况可能会使用复制构造函数:
一、初始化;
二、函数的传值调用;
三、函数调用返回一个类对象;
四、需要产生一个临时类对象时。
练习13.2
解释为什么下面的声明是非法的:
Sales_data::Sales_data(Sales_data rhs);
解答:
1. 不能在类外部声明构造函数,可以在外部实现构造函数。
2. 参数中的形参必须是引用形式。
练习13.3
当我们拷贝一个StrBlob时,会发生什么?拷贝一个StrBlobPtr呢?
解答:
首先,这两个函数需要有拷贝构造函数。在之前我们构造的类中,拷贝构造函数是没有的。
StrBlob中的data是shared_ptr,StrBlobPtr中data的weak_ptr,我想除了对与指针引用计数的影响,其他都不影响。
练习13.4
假定Point是一个类类型,它有一个public的拷贝构造函数,指出下面程序片段中哪些地方使用了拷贝构造函数:
Point global;
Point foo_bar(Point arg){
Point local = arg;
Point *heap = new Point(global);
*heap = local;
Point pa[4] = {local, *heap};
return *heap;
}
解答:
其实这里写一个简单的拷贝构造函数就可以验证。
#include <iostream>
#include <string>
using namespace std;
class Point{
public:
Point(){};
Point(const Point&);
string *p;
};
Point::Point(const Point& ptr){
cout << "use construction funcion" << endl;
p = ptr.p;
}
Point global;
Point foo_bar(Point arg){ ①
Point local = arg; ②
Point *heap = new Point(global); ③
*heap = local;
Point pa[4] = {local④, *heap⑤};
return *heap;⑥
}
int main(){
Point p;
foo_bar(p);
}
发现程序会打印出来6段拷贝构造函数中的字符串。
在哪会打印出来这个字符串,我已经标明。
自己没测试之前以为是5次,但是在return的时候还是做了一次拷贝,所以就是六次了。
练习13.5
给定下面的类框架,编写一个拷贝构造函数,拷贝所有成员。
你的够着函数应该动态分配一个新的string(参见12.1.2节,第407页),并将对象拷贝到ps指向的位置,而不是ps本身。
class HasPtr{
public:
HasPtr(const string &s = string()):ps(new string(s)), i(0){}
private:
string *ps;
int i;
};
解答:
#include <iostream>
#include <string>
using namespace std;
class HasPtr{
public:
HasPtr(const string &s = string()):ps(new string(s)), i(0){}
HasPtr(const HasPtr& ori):ps(new string(*(ori.ps))), i(ori.i){}; // 拷贝构造函数
//private: //这里注掉private属性,只是为了简单验证
string *ps;
int i;
};
int main(){
HasPtr a("test string");
cout << a.ps << endl;
cout << *(a.ps) << endl;
HasPtr b(a);
cout << b.ps << endl;
cout << *(b.ps) << endl;
}