C++ Primer(5e)第13章习题

13.1

如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。
使用时候:
1.用=定义变量
2.将要给对象作为实参传递给一个非引用类型的实参
3.从一个返回类型为非引用类型的函数返回一个对象
4.用花括号列表初始化一个数组中的元素或一个聚合类中的成员

13.2

因为如果拷贝构造函数的参数不是引用类型,则调动永远也不会成功:为了调用拷贝构造函数,我们必须拷贝它的实参,但为了拷贝实参,我们又需要调用拷贝构造函数,如此无限循环。

13.3

拷贝其中的资源和对象;拷贝其中的指针。

13.4

都使用了拷贝构造函数

13.5

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

13.6

拷贝赋值运算符就是接受一个与其所在类相同类型的参数,返回一个指向其左侧运算对象的引用并名为operator=的函数;当使用=运算符时使用该函数; 合成拷贝赋值运算法类似拷贝构造函数;如果一个类未定义自己的拷贝赋值运算符,编译器会为它生成一个合成拷贝赋值运算符。

13.7

赋值其中的资源和对象; 赋值其中的指针对象

13.8

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

13.9

析构函数是类的一个成员函数,名字由波浪号接类名构成,它没有返回值,也不接受参数;
合成析构函数被用来阻止该类型的对象被销毁;
当一个类未定义自己的析构函数时,编译器会为它定义一个合成析构函数

13.10

析构函数执行;
析构函数不会执行

13.11

~HasPtr() { }

13.12

3次

13.13

struct X {
	X& operator=(const X&);
	~X();
};

13.14

都输出同样的内容

13.15

会改变,拷贝构造函数生成的序号独一无二

13.16

如果类中有拷贝构造函数,则结果会改变;如果没有,则结果不变

13.17

/* 练习13.14 */
#include

using namespace std;

class numbered
{
public:
	int mysn;
	numbered() { mysn = rand() % 100; }

};

void f(numbered s)
{
	cout << s.mysn << endl;
}

int main()
{
	numbered a, b = a, c = b;
	f(a);
	f(b);
	f(c);
	system("pause");
	return 0;
}
/* 练习13.15 */
#include

using namespace std;

class numbered
{
public:
	int mysn;
	numbered(numbered& nd)
	{
		mysn = rand() % 100;
	}
};

void f(numbered s)
{
	cout << s.mysn << endl;
}

int main()
{
	numbered a, b = a, c = b;
	f(a);
	f(b);
	f(c);
	system("pause");
	return 0;
}
/* 13.16 */
#include

using namespace std;

class numbered
{
public:
	int mysn;
	numbered() { mysn = rand() % 100; }
};

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

int main()
{
	numbered a, b = a, c = b;
	f(a);
	f(b);
	f(c);
	
	
	system("pause");
	return 0;
}

13.18

class Employee
{
public:
	Employee() { num++; }
	Employee(string n) : name(n), id (num++) { }

private:
	int id;
	static int num;
	string name;
};

int Employee::num = 0;

13.19

需要,我们需要独一无二的证号

class Employee
{
public:
	Employee() { num++; }
	Employee(string n) : name(n), id (num++) { }
	Employee(const Employee &ep)
	{
		name = ep.name;
		id = num++;
	}
	Employee& operator=(const Employee &ep)
	{
		name = ep.name;
		return *this;
	}

private:
	int id;
	static int num;
	string name;
};

int Employee::num = 0;

13.22

class HasPtr
{
public:
	HasPtr(const string &s = string()) :
		ps(new string(s)), i(0) { }
	HasPtr(const HasPtr &p) :
		ps(new string(*p.ps)), i(p.i) { }
	HasPtr& operator=(const HasPtr &hp)
	{
		auto newp = new string(*hp.ps);
		delete ps;
		ps = newp;
		i = hp.i;
		return *this;
	}
	~HasPtr() { delete ps; }
private:
	string *ps;
	int i;
};

13.24

未定义析构函数:内存泄漏
未定义拷贝构造函数:多次释放同一指针资源

13.27

/* 书上例子敲一遍也是极好的 */
class HasPtr
{
public:
	HasPtr(const string &s = string()) :
		ps(new string(s)), i(0), use(new size_t(1)) { }
	HasPtr(const HasPtr &p) :
		ps(p.ps), i(p.i), use(p.use) {
		++*use;
	}
	HasPtr& operator=(const HasPtr);
	~HasPtr();
private:
	string *ps;
	int i;
	size_t *use;
};

HasPtr::~HasPtr()
{
    if (--*use == 0)
    {
        delete ps;
        delete use;
    }
}

HasPtr& 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;
}

13.28

/* a选项 */
class TreeNode
{
public:
	TreeNode() : count(0), left(nullptr), right(nullptr), use(new size_t(1)) { }
	TreeNode(TreeNode &tn)
	{
		++*tn.use;
		use = tn.use;
		value = tn.value;
		left = tn.left;
		right = tn.right;
		count = tn.count;
	}
	TreeNode& operator=(TreeNode &tn)
	{
		++*tn.use;
		if (--*use == 0)
		{
			delete use;
			if (left)
				delete left;
			if (right)
				delete right;
		}
		count = tn.count;
		value = tn.value;
		left = tn.left;
		right = tn.right;
	}
	~TreeNode()
	{
		if (--*use == 0)
		{
			delete use;
			if (left)
			{
				delete left;
				left = nullptr;
			}
			if (right)
			{
				delete right;
				right = nullptr;
			}
		}
	}
private:
	string value;
	int count;
	TreeNode *left;
	TreeNode *right;
	size_t *use;
};

/* b选项 */
class BinStrTree
{
public:
	BinStrTree() : root(new TreeNode()) { }
	BinStrTree(BinStrTree &bst)
	{
		root = new TreeNode(*bst.root);
	}
	BinStrTree& operator=(BinStrTree& bst)
	{
		auto new_root = new TreeNode(*bst.root);
		delete root;
		root = new_root;
		return *this;
	}
	~BinStrTree()
	{
		delete root;
	}
private:
	TreeNode *root;
};

13.29

交换了指针,而不是指针所指的数据

13.30

void swap(HasPtr &lhs, HasPtr &rhs)
{
	using std::swap;
	swap(lhs.i, rhs.i);
	swap(lhs.ps, rhs.ps);
}

13.31

不会,类指针的HasPtr版本不用分配动态内存

等待二刷

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