C++拷贝

第一遍看这部分(P452)确实很难理解,回头对照英文的再看看。

拷贝

HasPtr类

这一小节开篇第一句话就让我头大。“管理类外资源的类必须定义拷贝控制成员”
通过不断翻书追根溯源,我捋了一下如何理解这句话。首先我们来看书中所提供的HasPtr类(我这里省略了std作用域):

class HasPtr{
public:
    //动态分配一个新的string
    HasPtr(const string &s = string()):
            ps(new string(s)), i(0) { }
    //拷贝对象p到ps指向的地址
    HasPtr(const HasPtr& p):
            ps(new string(*p.ps)), i(*p.i) { }
private:
    string *ps;
    int i;
};
HasPtr(const string &s = string()): ps(), i() { }

构造函数的默认实参s是一个string类型的引用,为空字符串;冒号后面是数据成员ps和i的初值。

HasPtr(const HasPtr& p): ps(new string(*p.ps)), i(*p.i) { }

拷贝构造函数,把p的成员函数ps的地址和i值赋给新的对象

Synthesied copy constructor

如果没有为类定义一个拷贝构造函数,编译器会为我们定义一个synthesied copy constructor。
等价于如下的copy constructor:

class Sales_data{
public:
    Sales_data(const Sales_data&);
private:
    string bookNo;
    int units_sold=0;
    double revenue = 0.0;
}
Sales_data::Sales_data(const Sales_data &orig):
    bookNo(orig.bookNo), units_sold(orig.units_sold), 
    revenue(orig.revenue)
    { }

可以发现synthesied copy constructor把成员数据的默认值赋给对象orig。

Synthesied destructor

当类未定义自己的析构函数时,编译器会为它定义一个合成析构函数(synthesied destructor)

class Saled_data{
public:
    ~Sales_data() { }
    ...
};

从代码中可以看到,合成析构函数只销毁其成员,而动态分配的指针则需要使用delete来销毁。
因此需要类来定义一个析构函数。

三五法则

需要析构函数的类也需要定义拷贝构造函数和拷贝赋值运算符

class HasPtr{
public:
    HasPtr(const string &s = string()): ps(), i() { }
    ~HasPtr() { delete ps; }
    ...
};

假如我们为HasPtr类定义了一个析构函数,但是使用的是合成版本的拷贝构造函数,那么看下面这个函数:

HasPtr f(HasPtr hp){
    HasPtr res = hp;
    return res;
}

对象hp接受类HasPtr数据成员的默认值。
将对象hp作为参数传入函数f();将hp的内存地址赋给res;函数声明周期结束时销毁res和hp,这两个对象都会调用HasPtr的析构对象。

全部评论

相关推荐

头像
不愿透露姓名的神秘牛友
04-29 12:10
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务