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的析构对象。

全部评论

相关推荐

08-08 16:33
唐山学院 Java
职场水母:首先,简历太长,对于实习和应届找工作,hr一眼扫的是学历,技术看实习,你写的技术栈字太多了,尽量用一句话概括不用写那么详细,技术面的时候会问的,而且技术栈都会在实习或者项目里体现,你要做的是,把你的简历浓缩为一页,删除没用的东西,比如实践经历,自我评价,这些纯废话,没用,专业技能写的太离谱,你真的熟练掌握了吗,建议都写熟悉,找工作和写论文不一样,追求的是干练和实用,把实习经历和项目提前,把掌握的技术栈写到最后,然后去找实习,
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务