【足迹C++primer】42、13_1_拷贝、赋值与销毁(2)

13_1_拷贝、赋值与销毁(2)

13.1.4 三/五法则

需要析构函数的类也需要拷贝和赋值操作

class HasPtr
{
public:
    HasPtr(const string &s=string()):ps(new string(s)), i(0){}
    ~HasPtr()   {delete ps;}
    /*
        这里需要一个拷贝构造函数和一个拷贝赋值运算符
        如果不加上这两个,请看下面
    */
private:
    string *ps;
    int i;
};

HasPtr fun1(HasPtr hp)  //HasPtr是传值参数,所有将被拷贝
{
    HasPtr ret=hp;      //拷贝给定的HasPtr
    //处理ret
    return ret;         //ret和hp被销毁
}

由于ret和hp两个指针是赋值一样的,那么指向的内存一样,ret和hp被销毁
调用delete析构函数,则同一块空间被delete了两次 

如果一个类需要自定义析构函数,几乎可以肯定它也需要自定义拷贝赋值运算符和拷贝构造函数

13.1.5使用=default

class Sales_data
{
friend Sales_data add(const Sales_data&, const Sales_data&);
friend ostream &print(ostream&, const Sales_data&);
friend istream &read(istream&, Sales_data&);
public:
	Sales_data(const string &s):
	           bookNo(s), units_sold(0), revenue(0.0) { }
	Sales_data(const string &s, unsigned n, double p):
	           bookNo(s), units_sold(n), revenue(p*n) { }
	Sales_data(istream &);

	// operations on Sales_data objects
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	double avg_price() const;

	/*
    与合成的拷贝构造函数等价的拷贝构造函数的声明
    */
    Sales_data()=default;
    Sales_data(const Sales_data&)=default;
    Sales_data& operator=(const Sales_data&);   //赋值运算符
    ~Sales_data()=default;
private:
	string bookNo;
	int units_sold=0;
	double revenue=0.0;
};

//与Sales_data的合成的拷贝构造函数等价
/*Sales_data::Sales_data(const Sales_data &orig):bookNo(orig.bookNo),
                       units_sold(orig.units_sold),revenue(orig.revenue){}*/

// nonmember Sales_data interface functions
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);
istream &read(istream&, Sales_data&);

// used in future chapters
inline
bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
	return lhs.isbn() < rhs.isbn();
}

//拷贝赋值运算符
Sales_data& Sales_data::operator=(const Sales_data&)=default;   //在类外定义时用default则不是内联函数

13.1.6 阻止拷贝

大多数类应该定义默认构造函数、拷贝构造函数和拷贝赋值运算符,无论是隐式地还是显示地

定义删除函数

我们可以将拷贝构造函数和拷贝赋值运算符定义为删除函数来阻止拷贝
struct NoCopy
{
    NoCopy()=default;   //使用合成的默认构造函数
    NoCopy(const NoCopy&)=delete;   //阻止拷贝
    NoCopy &operator=(const NoCopy&)=delete;    //阻止赋值
    ~NoCopy()=default;      //使用合成的析构函数
    //其他成员
};

析构函数不能使删除的成员

struct NoDtor
{
    NoDtor()=default;   //使用合成的默认构造函数
//    ~NoDtor()=delete;      //使用合成的析构函数,我们不能销毁NoDtor类型的对象
    //其他成员
};

void fun2()
{
    NoDtor nd;  //错误:NoDtor的析构函数式删除的
    NoDtor *p=new NoDtor();     //正确:但我们不能delete p
    delete p;       //错误:NoDtor的析构函数式删除的
}

private拷贝控制

在新标准之前,类是通过将其拷贝构造函数和拷贝赋值运算符声明为private的来阻止拷贝
class PrivateCopy
{
    //无妨问说明符;接下来的成员默认为private的
    //拷贝控制成员是private的,因此普通用户代码无法访问
    privateCopy(const PrivateCopy&);
    privateCopy &operator=(const PrivateCopy&);
    //其他成员
public:
    privateCopy()=default;  //使用合成的默认构造函数
    ~privateCopy();         //用户可以定义此类型的对象,但无法拷贝他们
};

来人!!上代码~~~~

/**
* 功能:13_1_拷贝、赋值与销毁
* 时间:2014年7月12日08:36:15
* 作者:cutter_point
*/

#include<iostream>
#include<string>

using namespace std;

/**************************************
13.1.4 三/五法则
**************************************/

/**
需要析构函数的类也需要拷贝和赋值操作
*/
class HasPtr
{
public:
    HasPtr(const string &s=string()):ps(new string(s)), i(0){}
    ~HasPtr()   {delete ps;}
    /*
        这里需要一个拷贝构造函数和一个拷贝赋值运算符
        如果不加上这两个,请看下面
    */
private:
    string *ps;
    int i;
};

HasPtr fun1(HasPtr hp)  //HasPtr是传值参数,所有将被拷贝
{
    HasPtr ret=hp;      //拷贝给定的HasPtr
    //处理ret
    return ret;         //ret和hp被销毁
}
/*
由于ret和hp两个指针是赋值一样的,那么指向的内存一样,ret和hp被销毁
调用delete析构函数,则同一块空间被delete了两次
*/

/*
如果一个类需要自定义析构函数,几乎可以肯定它也需要自定义拷贝赋值运算符和拷贝构造函数
*/

/**************************************
13.1.5使用=default
**************************************/
class Sales_data
{
friend Sales_data add(const Sales_data&, const Sales_data&);
friend ostream &print(ostream&, const Sales_data&);
friend istream &read(istream&, Sales_data&);
public:
	Sales_data(const string &s):
	           bookNo(s), units_sold(0), revenue(0.0) { }
	Sales_data(const string &s, unsigned n, double p):
	           bookNo(s), units_sold(n), revenue(p*n) { }
	Sales_data(istream &);

	// operations on Sales_data objects
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	double avg_price() const;

	/*
    与合成的拷贝构造函数等价的拷贝构造函数的声明
    */
    Sales_data()=default;
    Sales_data(const Sales_data&)=default;
    Sales_data& operator=(const Sales_data&);   //赋值运算符
    ~Sales_data()=default;
private:
	string bookNo;
	int units_sold=0;
	double revenue=0.0;
};

//与Sales_data的合成的拷贝构造函数等价
/*Sales_data::Sales_data(const Sales_data &orig):bookNo(orig.bookNo),
                       units_sold(orig.units_sold),revenue(orig.revenue){}*/

// nonmember Sales_data interface functions
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);
istream &read(istream&, Sales_data&);

// used in future chapters
inline
bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
	return lhs.isbn() < rhs.isbn();
}

//拷贝赋值运算符
Sales_data& Sales_data::operator=(const Sales_data&)=default;   //在类外定义时用default则不是内联函数

/**************************************
13.1.6 阻止拷贝
**************************************/

/*
大多数类应该定义默认构造函数、拷贝构造函数和拷贝赋值运算符,无论是隐式地还是显示地
*/
/**
定义删除函数
*/

/*
我们可以将拷贝构造函数和拷贝赋值运算符定义为删除函数来阻止拷贝
*/
struct NoCopy
{
    NoCopy()=default;   //使用合成的默认构造函数
    NoCopy(const NoCopy&)=delete;   //阻止拷贝
    NoCopy &operator=(const NoCopy&)=delete;    //阻止赋值
    ~NoCopy()=default;      //使用合成的析构函数
    //其他成员
};

/**
析构函数不能使删除的成员
*/
struct NoDtor
{
    NoDtor()=default;   //使用合成的默认构造函数
//    ~NoDtor()=delete;      //使用合成的析构函数,我们不能销毁NoDtor类型的对象
    //其他成员
};

void fun2()
{
    NoDtor nd;  //错误:NoDtor的析构函数式删除的
    NoDtor *p=new NoDtor();     //正确:但我们不能delete p
    delete p;       //错误:NoDtor的析构函数式删除的
}

/**
private拷贝控制
*/

/*
在新标准之前,类是通过将其拷贝构造函数和拷贝赋值运算符声明为private的来阻止拷贝
*/
class PrivateCopy
{
    //无妨问说明符;接下来的成员默认为private的
    //拷贝控制成员是private的,因此普通用户代码无法访问
    privateCopy(const PrivateCopy&);
    privateCopy &operator=(const PrivateCopy&);
    //其他成员
public:
    privateCopy()=default;  //使用合成的默认构造函数
    ~privateCopy();         //用户可以定义此类型的对象,但无法拷贝他们
};

int main()
{

    return 0;
}


PS:生活就是这么瞬息万变,前一秒还好好的,下一秒没准就是狂风暴雨,不可掉以轻心啊,特别是取得成功的时候,也就是特别容易失败的时刻,最后我只想说,感冒虐我千百遍,我待感冒如初恋,它来一次只要我好了,身体就会产生抗体,我就不怕感冒了,祸兮,福之所倚啊!!!!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值