拷贝构造函数是什么?什么时候使用它?
如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。当使用拷贝初始化时,我们会用到拷贝构造函数。
解释为什么下面的声明是非法的:
Sales_data::Sales_data(Sales_data rhs);
参数类型应该是引用类型。
当我们拷贝一个StrBlob时,会发生什么?拷贝一个StrBlobPtr呢?
当我们拷贝 StrBlob时,会使 shared_ptr
的引用计数加1。当我们拷贝 StrBlobPtr 时,引用计数不会变化。
假定 Point 是一个类类型,它有一个public的拷贝构造函数,指出下面程序片段中哪些地方使用了拷贝构造函数:
Point global;
Point foo_bar(Point arg) // 1
{
Point local = arg, *heap = new Point(global); // 2: Point local = arg, 3: Point *heap = new Point(global)
*heap = local;
Point pa[4] = { local, *heap }; // 4, 5
return *heap; // 6
}
上面有6处地方使用了拷贝构造函数。
给定下面的类框架,编写一个拷贝构造函数,拷贝所有成员。你的构造函数应该动态分配一个新的string,并将对象拷贝到ps所指向的位置,而不是拷贝ps本身:
class HasPtr {
public:
HasPtr(const std::string& s = std::string()):
ps(new std::string(s)), i(0) { }
private:
std::string *ps;
int i;
}
#ifndef ex13_5_h
#define ex13_5_h
#include
class HasPtr
{
public:
HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) {}
HasPtr(const HasPtr& hp) :ps(new std::string(*hp.ps)), i(hp.i) {}
private:
std::string *ps;
int i;
};
#endif
拷贝赋值运算符是什么?什么时候使用它?合成拷贝赋值运算符完成什么工作?什么时候会生成合成拷贝赋值运算符?
拷贝赋值运算符是一个名为 operator=
的函数。当赋值运算发生时就会用到它。合成拷贝赋值运算符可以用来禁止该类型对象的赋值。如果一个类未定义自己的拷贝赋值运算符,编译器会为它生成一个合成拷贝赋值运算符。
当我们将一个 StrBlob 赋值给另一个 StrBlob 时,会发生什么?赋值 StrBlobPtr 呢?
会发生浅层复制。
为13.1.1节练习13.5中的 HasPtr 类编写赋值运算符。类似拷贝构造函数,你的赋值运算符应该将对象拷贝到ps指向的位置。
#ifndef ex13_8_h
#define ex13_8_h
#include
class HasPtr
{
public:
HasPtr(const std::string& s = std::string()) :ps(new std::string()), i(0) {}
HasPtr(const HasPtr& hp) :ps(new std::string(*hp.ps)), i(hp.i) {}
HasPtr& operator=(const HasPtr& hp)
{
std::string *new_ps = new std::string(*hp.ps);
delete ps;
ps = new_ps;
i = hp.i;
return *this;
}
private:
std::string *ps;
int i;
};
#endif // !ex13_8_h
析构函数是什么?合成析构函数完成什么工作?什么时候会生成合成析构函数?
析构函数是类的一个成员函数,名字由波浪号接类名构成。它没有返回值,也不接受参数。合成析构函数可被用来阻止该类型的对象被销毁。当一个类未定义自己的析构函数时,编译器会为它生成一个合成析构函数。
当一个 StrBlob 对象销毁时会发生什么?一个 StrBlobPtr 对象销毁时呢?
当一个 StrBlob 对象被销毁时,shared_ptr
的引用计数会减少。当 StrBlobPtr 对象被销毁时,不影响引用计数。