Skip to content

Commit

Permalink
Add soultions to first half of exercises in chapter 13.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaege committed Feb 5, 2016
1 parent 86dd48a commit 3e4f933
Show file tree
Hide file tree
Showing 35 changed files with 1,064 additions and 4 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,18 @@ This repo is the solutions to exercises in book [_C++ Primer_ (5th Edition)](htt
[21](ch12/12.21.md)|[22](ch12/12.22)|[23](ch12/12.23.cpp)|[24](ch12/12.24.cpp)|[25](ch12/12.25.md)|[26](ch12/12.26.cpp)|[27](ch12/12.27)|[28](ch12/12.28.cpp)|[29](ch12/12.29.cpp)|[30](ch12/12.30)|
[31](ch12/12.31.md)|[32](ch12/12.32)|[33](ch12/12.33)

<!---
#### Chapter 13 [Copy Control](ch13)

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
--:|--:|--:|--:|--:|--:|--:|--:|--:|--:
[1](ch13/13.1.cpp)|[2](ch13/13.2.cpp)|[3](ch13/13.3.cpp)|[4](ch13/13.4.cpp)|[5](ch13/13.5.cpp)|[6](ch13/13.6.cpp)|[7](ch13/13.7.cpp)|[8](ch13/13.8.cpp)|[9](ch13/13.9.cpp)|[10](ch13/13.10.cpp)|
[11](ch13/13.11.cpp)|[12](ch13/13.12.cpp)|[13](ch13/13.13.cpp)|[14](ch13/13.14.cpp)|[15](ch13/13.15.cpp)|[16](ch13/13.16.cpp)|[17](ch13/13.17.cpp)|[18](ch13/13.18.cpp)|[19](ch13/13.19.cpp)|[20](ch13/13.20.cpp)|
[21](ch13/13.21.cpp)|[22](ch13/13.22.cpp)|[23](ch13/13.23.cpp)|[24](ch13/13.24.cpp)|[25](ch13/13.25.cpp)|[26](ch13/13.26.cpp)|[27](ch13/13.27.cpp)|[28](ch13/13.28.cpp)|[29](ch13/13.29.cpp)|[30](ch13/13.30.cpp)|
[1](ch13/13.1.md)|[2](ch13/13.2.md)|[3](ch13/13.3.md)|[4](ch13/13.4.md)|[5](ch13/13.5.cpp)|[6](ch13/13.6.md)|[7](ch13/13.7.md)|[8](ch13/13.8.cpp)|[9](ch13/13.9.md)|[10](ch13/13.10.md)|
[11](ch13/13.11.cpp)|[12](ch13/13.12.md)|[13](ch13/13.13.cpp)|[14](ch13/13.14.cpp)|[15](ch13/13.15.cpp)|[16](ch13/13.16.cpp)|[17](ch13/13.17.md)|[18](ch13/13.18.cpp)|[19](ch13/13.19.cpp)|[20](ch13/13.20.md)|
[21](ch13/13.21.md)|[22](ch13/13.22.md)|[23](ch13/13.23.cpp)|[24](ch13/13.24.md)|[25](ch13/13.25.md)|[26](ch13/13.26)|[27](ch13/13.27.cpp)|[28](ch13/13.28.cpp)|[29](ch13/13.29.cpp)|[30](ch13/13.30.cpp)|
[31](ch13/13.31.cpp)|[32](ch13/13.32.cpp)|[33](ch13/13.33.cpp)|[34](ch13/13.34.cpp)|[35](ch13/13.35.cpp)|[36](ch13/13.36.cpp)|[37](ch13/13.37.cpp)|[38](ch13/13.38.cpp)|[39](ch13/13.39.cpp)|[40](ch13/13.40.cpp)|
[41](ch13/13.41.cpp)|[42](ch13/13.42.cpp)|[43](ch13/13.43.cpp)|[44](ch13/13.44.cpp)|[45](ch13/13.45.cpp)|[46](ch13/13.46.cpp)|[47](ch13/13.47.cpp)|[48](ch13/13.48.cpp)|[49](ch13/13.49.cpp)|[50](ch13/13.50.cpp)|
[51](ch13/13.51.cpp)|[52](ch13/13.52.cpp)|[53](ch13/13.53.cpp)|[54](ch13/13.54.cpp)|[55](ch13/13.55.cpp)|[56](ch13/13.56.cpp)|[57](ch13/13.57.cpp)|[58](ch13/13.58.cpp)

<!---
#### Chapter 14 [Overloaded Operations and Conversions](ch14)
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
Expand Down
3 changes: 3 additions & 0 deletions ch13/13.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
A copy constructor is a constructor whose first parameter is a reference to the class type and any additional parameters have default values.

The copy constructor may be used when we use copy initialization, but not always.
3 changes: 3 additions & 0 deletions ch13/13.10.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
When a `StrBlob` object is destroyed, the shared pointer member is destroyed by calling the pointer's destructor, thus decreasing the reference count of the shared pointer, if the count is zero, then the vector pointed by the smart pointer is destroyed too.

When a `StrBlobPtr` object is destroyed, the weak pointer member is destroyed by calling the pointer's destructor, the vector pointed by the smart pointer is not affected.
49 changes: 49 additions & 0 deletions ch13/13.11.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <string>
#include <iostream>

class HasPtr {
public:
HasPtr(const std::string &s = std::string())
: ps(new std::string(s)), i(0) {}
HasPtr(const HasPtr &ori)
: ps(new std::string(*ori.ps)), i(ori.i) {}
~HasPtr();

HasPtr &operator=(const HasPtr &rhs);

const std::string &get() const { return *ps; }
void set(const std::string &s) { *ps = s; }

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

HasPtr::~HasPtr() {
delete ps;
}

HasPtr &HasPtr::operator=(const HasPtr &rhs) {
// This copy-assignment operator is wrong, see ex13.23 for correct version.
delete ps;
ps = new std::string(*rhs.ps);
i = rhs.i;
return *this;
}

int main() {
HasPtr hp1 = "World";
HasPtr hp2 = hp1;
HasPtr hp3;
hp3 = hp1;
hp1.set("Hello");

std::cout << hp1.get() << std::endl;
std::cout << hp2.get() << std::endl;
std::cout << hp3.get() << std::endl;

hp1 = hp1;
std::cout << "After `hp1 = hp1`: " << hp1.get() << std::endl;

return 0;
}
7 changes: 7 additions & 0 deletions ch13/13.12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bool fcn(const Sales_data *trans, Sales_data accum)
{
Sales_data item1(*trans), item2(accum);
return item1.isbn() != item2.isbn();
}

3 destructors are called on `accum`, `item1` and `item2`.
73 changes: 73 additions & 0 deletions ch13/13.13.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <iostream>
#include <vector>
#include <list>

struct X {
X() { ++i; j = i; std::cout << "X() " << j << std::endl; }
X(const X &) { ++i; j = i; std::cout << "X(const X &) " << j << std::endl; }
X &operator=(const X &) { std::cout << "operator= " << j << std::endl; }
~X() { std::cout << "~X() " << j << std::endl; }
static int i;
int j;
};

int X::i = 0;

void f1(X x) {
}

void f2(X &x) {
}

X f3() {
return X();
}

X f5() {
X x;
return x;
}

X &f4(X &x) {
return x;
}

int main() {
std::cout << "\n----- X x1;\n";
X x1;
std::cout << "\n----- f1(x1);\n";
f1(x1);
std::cout << "\n----- f2(x1);\n";
f2(x1);
std::cout << "\n----- X x3 = f3();\n";
X x3 = f3();
std::cout << "\n----- f3();\n";
f3();
std::cout << "\n----- X x5 = f5();\n";
X x5 = f5();
std::cout << "\n----- f5();\n";
f5();
std::cout << "\n----- X x4 = f4(x1);\n";
X x4 = f4(x1);
std::cout << "\n----- f4(x1);\n";
f4(x1);
std::cout << "\n----- X *x2 = new X;\n";
X *x2 = new X;
std::cout << "\n----- std::vector<X> vx;\n";
std::vector<X> vx;
std::cout << "\n----- vx.push_back(x1);\n";
vx.push_back(x1);
std::cout << "\n----- vx.push_back(*x2);\n";
vx.push_back(*x2); // The vector is reallocate here.
std::cout << "\n----- std::list<X> vl;\n";
std::list<X> vl;
std::cout << "\n----- vl.push_back(x1);\n";
vl.push_back(x1);
std::cout << "\n----- vl.push_back(*x2);\n";
vl.push_back(*x2); // The list does not need reallocate.
std::cout << "\n----- delete x2;\n";
delete x2;
std::cout << "\n----- \n";

return 0;
}
27 changes: 27 additions & 0 deletions ch13/13.14.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <iostream>
using std::cout; using std::endl;

class numbered {
public:
numbered() : mysn(++sn) {}
int mysn;
private:
static int sn;
};

int numbered::sn = 0;

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

int main() {
numbered a, b = a, c = b;
f(a); // 1
f(b); // 1
f(c); // 1
numbered d;
f(d); // 2

return 0;
}
30 changes: 30 additions & 0 deletions ch13/13.15.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <iostream>
using std::cout; using std::endl;

class numbered {
public:
numbered() : mysn(++sn) {}
numbered(const numbered &) : mysn(++sn) {}
int mysn;
private:
static int sn;
};

int numbered::sn = 0;

void f(numbered s) {
// `s` is copy initialized from argument, thus `s.mysn` is not the same with
// the argument we passed in.
cout << s.mysn << endl;
}

int main() {
numbered a, b = a, c = b; // a.mysn = 1, b.mysn = 2, c.mysn = 3
f(a); // 4
f(b); // 5
f(c); // 6
numbered d;
f(d); // 8

return 0;
}
28 changes: 28 additions & 0 deletions ch13/13.16.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <iostream>
using std::cout; using std::endl;

class numbered {
public:
numbered() : mysn(++sn) {}
numbered(const numbered &) : mysn(++sn) {}
int mysn;
private:
static int sn;
};

int numbered::sn = 0;

void f(const numbered &s) { // the reference will not use copy initialization
cout << s.mysn << endl;
}

int main() {
numbered a, b = a, c = b; // a.mysn = 1, b.mysn = 2, c.mysn = 3
f(a); // 1
f(b); // 2
f(c); // 3
numbered d;
f(d); // 4

return 0;
}
1 change: 1 addition & 0 deletions ch13/13.17.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
See [ex13.14](ex13.14.cpp), [ex13.15](ex13.15.cpp) and [ex13.16](ex13.16.cpp).
29 changes: 29 additions & 0 deletions ch13/13.18.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <string>
#include <iostream>

class Employee {
public:
typedef int id_type;
Employee() : name(), id(++eid) {}
explicit Employee(const std::string &n) : name(n), id(++eid) {}

const std::string &getName() const { return name; }
id_type getID() const { return id; }

private:
std::string name;
id_type id;
static id_type eid;
};

Employee::id_type Employee::eid = 0;

int main() {
Employee e1;
Employee e2("Zhang San");

std::cout << e1.getName() << " " << e1.getID() << std::endl;
std::cout << e2.getName() << " " << e2.getID() << std::endl;

return 0;
}
46 changes: 46 additions & 0 deletions ch13/13.19.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// The Employee class need to define its own versions of the copy-control
// members, because we must ensure that the copyed object has different ID from
// the original object.

#include <string>
#include <iostream>

class Employee {
public:
typedef int id_type;

Employee() : name(), id(++eid) {}
explicit Employee(const std::string &n) : name(n), id(++eid) {}
Employee(const Employee &e) : name(e.name), id(++eid) {}

Employee &operator=(const Employee &e);

const std::string &getName() const { return name; }
id_type getID() const { return id; }

private:
std::string name;
id_type id;
static id_type eid;
};

Employee::id_type Employee::eid = 0;

Employee &Employee::operator=(const Employee &e) {
name = e.name;
//id = ++eid; // keep the old id
return *this;
}

int main() {
Employee e1;
std::cout << e1.getName() << " " << e1.getID() << std::endl;
Employee e2("Zhang San");
std::cout << e2.getName() << " " << e2.getID() << std::endl;
Employee e3 = e2;
std::cout << e3.getName() << " " << e3.getID() << std::endl;
e1 = e2;
std::cout << e1.getName() << " " << e1.getID() << std::endl;

return 0;
}
1 change: 1 addition & 0 deletions ch13/13.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The parameter of the constructor should be a reference, otherwise the call would never succeed. To call the copy constructor, we'd need to use the copy constructor to copy the argument, but to copy the argument, we'd need to call the copy constructor, and so on indefinitely.
11 changes: 11 additions & 0 deletions ch13/13.20.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
- Copy `TextQuery` or `QueryResult`

The data member (built-in type, class type, smart pointer and container) of the class is copyed, in which the smart pointer is copyed and the reference count is increased.

- Assign `TextQuery` or `QueryResult`

The data member (built-in type, class type, smart pointer and container) of the class is copyed, in which the smart pointer is copyed and the new reference count is increased, the old reference count is decreased.

- Destory `TextQuery` or `QueryResult`

The data member (built-in type, class type, smart pointer and container) of the class is destroyed, in which the smart pointer is destroyed and the reference count is decreased.
1 change: 1 addition & 0 deletions ch13/13.21.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
No, they don't need. Becasue all the members of class `TextQuery` and `QueryResult` are copyed or destroyed correctly by the synthesized copy-control members.
1 change: 1 addition & 0 deletions ch13/13.22.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
See [ex13.11](13.11.cpp).
51 changes: 51 additions & 0 deletions ch13/13.23.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <string>
#include <iostream>

class HasPtr {
public:
HasPtr(const std::string &s = std::string())
: ps(new std::string(s)), i(0) {}
HasPtr(const HasPtr &ori)
: ps(new std::string(*ori.ps)), i(ori.i) {}
~HasPtr();

HasPtr &operator=(const HasPtr &rhs);

const std::string &get() const { return *ps; }
void set(const std::string &s) { *ps = s; }

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

HasPtr::~HasPtr() {
delete ps;
}

HasPtr &HasPtr::operator=(const HasPtr &rhs) {
// This copy-assignment operator is correct even if the object is assigned to
// itself. See ex13.11 for the wrong version.
auto newps = new std::string(*rhs.ps);
delete ps;
ps = newps;
i = rhs.i;
return *this;
}

int main() {
HasPtr hp1 = "World";
HasPtr hp2 = hp1;
HasPtr hp3;
hp3 = hp1;
hp1.set("Hello");

std::cout << hp1.get() << std::endl;
std::cout << hp2.get() << std::endl;
std::cout << hp3.get() << std::endl;

hp1 = hp1;
std::cout << "After `hp1 = hp1`: " << hp1.get() << std::endl;

return 0;
}
Loading

0 comments on commit 3e4f933

Please sign in to comment.