习题13.1
(1)如果一个函数的一个参数是自身类型的引用,且任何额外参数都有默认值,
那么它就是拷贝构造函数。
(2)以下三种对象需要调用该函数
一个对象作为函数参数,以值传递的方式传入函数体
一个对象作为函数返回值,以值传递的方式从函数返回
一个对象用于给另一个对象进行初始化的时候。
习题13.2
参数应该是Sales_data&类型
习题13.3
当我们拷贝StrBlor时,shared_ptr成员use_cout增加了一个
而拷贝StrBlobPtrs, weak_ptr成员use_cout并没有改变
习题13.4
Point global;
Point foo_bar(Point arg) // 传参拷贝1
{
Point local = arg, *heap = new Point(global); // 2, 3
*heap = local;
Point pa[ 4 ] = { local, *heap }; // 4, 5
return *heap; // 6
}
习题13.5
HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) {}
习题13.6
(1)拷贝赋值运算符 =
(2)当赋值运算发生的时候
(3)完成一些拷贝操作
(4)如果一个类没有定义的时候
习题13.7
赋值StrBlob,会拷贝出一个新的StrBlob。
拷贝StrBlobPtr,会将指针内容赋值给另一个StrBlobPtr,并不会产生新的对象
习题13.8
HasPtr& operator=(const HasPtr& hp)
{
std::string* new_ps = new std::string(*hp.ps);
delete ps;
ps = new_ps;
i = hp.i;
return *this;
}
习题13.9
析构函数释放对象所使用的资源;
析构函数首先执行函数体,然后销毁成员;
在类没有定义析构函数的时候生成。
习题13.10
当一个StrBlob对象销毁时,它会删除string* ps及int i,及它所使用的资源;
StrBlobPtr销毁,其所指向的对象不会被销毁。
习题13.11
~HasPtr(){delete ps;}//释放动态分配的内存。
习题13.12
3次
习题13.13
struct X {
X() { std::cout << "X()" << std::endl; }
X(const X& obj) : i(obj.i),j(new int()){ std::cout << "X(const X&)" << std::endl; }
X& operator=(const X& obj)
{
i = obj.i;
auto ptr = new int();
delete j;
j = ptr;
return *this;
}
~X() { delete j; }
int i;
int* j;
};
习题13.14
三个数字相同
习题13.15
会,三个数字会不同
在函数传参时,这时应该使用的的是拷贝构造函数而非默认构造函数
习题13.16
会,输出回合传进来的引用相同。
习题13.17
#include
class numbered {
public:
static int unique;
numbered()
{
mysn = ++unique;
}
numbered(numbered&)
{
mysn = ++unique;
}
int mysn;
};
int numbered::unique = 0;
void f(const numbered& s)
{
std::cout << s.mysn << std::endl;
}
int main()
{
numbered a, b = a, c = b;//a使用默认构造,b,c使用拷贝构造
f(a); // 拷贝构造
f(b); // 拷贝构造
f(c); // 拷贝构造
system("pause");
return 0;
}
在未定义拷贝构造函数时,我们使用的是默认拷贝构造函数,默认拷贝构造函数并没有自增操作。
习题3.18
.h
#include
using std::string;
class Employee {
public:
Employee();
Employee(const string& name);
const int id() const { return id_; }
private:
string name_;
int id_;
static int s_increment;
};
.c
int Employee::s_increment = 0;
Employee::Employee()
{
id_ = s_increment++;
}
Employee::Employee(const string& name)
{
id_ = s_increment++;
name_ = name;
}
习题13.19
需要,每个人都是不同的
习题13.20
它的成员(例如指针和容器)将会被拷贝/销毁
习题13.21
需要,TextQuery,会自行分配一个vector的内存。而另一个不需要
习题13.22
略,前面写过
习题13.23
需要删除原有的资源,再进行拷贝。
习题13.24
使用合成的默认析构/构造函数
习题13.25
拷贝构造函数,类的行为像指针,并不会为指针分配新的内存,而是拷贝内存
地址,因为它是weak_ptr,不进入智能指针的计数,因此不需要delete或者reset
习题13.26
略
习题13.27
class HasPtr {
public:
HasPtr(const std::string& s = std::string())
: ps(new std::string(s)), i(0), use(new size_t(1))
{
}
HasPtr(const HasPtr& hp) : ps(hp.ps), i(hp.i), use(hp.use) { ++*use; }
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;
}
~HasPtr()
{
if (--*use == 0) {
delete ps;
delete use;
}
}
private:
std::string* ps;
int i;
size_t* use;
};
习题13.29
调用的swap是不在同一命名空间的。
习题13.30
void swap(HasPtr& lhs, HasPtr& rhs)
{
using std::swap;
swap(lhs.ps, rhs.ps);
swap(lhs.i, rhs.i);
std::cout << "call swap(HasPtr& lhs, HasPtr& rhs)" << std::endl;
}
习题13.31
bool operator<(const HasPtr& lhs, const HasPtr& rhs)
{
return *lhs.ps < *rhs.ps;
}
习题13.32
得益于它在交换时,不需要额外的内存开销。
后面的类都分文件写在工程里了,有点懒,不想复制了。。。
后来再开一篇关于右值引用和move的博客,这个用不好很容易down掉,所以基本我见过的工程大多都是拷贝而不是move。
但是这个优化真的令人眼馋,如果用好可以提升一些性能,用不好。。。那就,到处找bug。。。