首页 > 代码库 > 【足迹C++primer】42、拷贝、赋值与销毁(1)

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

拷贝、赋值与销毁(1)

13.1.1拷贝构造函数

/**************************************
13.1.1拷贝构造函数
**************************************/

class Foo1
{
public:
    Foo1();              //默认构造函数
    Foo1(const Foo1&);    //拷贝构造函数
    //...
};

注意:拷贝构造函数的第一个参数必须是一个参数

合成拷贝构造函数

/**************************************
合成拷贝构造函数
**************************************/
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:
	// constructors
	Sales_data(): units_sold(0), revenue(0.0) { }
	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(const Sales_data&);
    Sales_data& operator=(const Sales_data&);   //赋值运算符
    ~Sales_data(){}
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();
}

这个类其实在前面第七章就说过了,只是前面那个没有拷贝构造函数,拷贝赋值运算符,析构函数数而已

拷贝初始化

/**************************************
拷贝初始化
**************************************/
void fun1()
{
    string dots(10, '.');   //直接初始化
    string s(dots);         //直接初始化
    string s2=dots;         //拷贝初始化
    string null_book="9-999-99999-9";   //拷贝初始化
    string nines=string(100, '9');      //拷贝初始化
}

拷贝初始化不仅在我们用=定义变量时会发生,在下列情况下也会发生
*将一个对象作为实参传递给一个非引用类型的形参
*从一个返回类型为非引用类型的函数返回一个对象
*用花括号列表初始化一个数组中的元素或一个聚合类中的成员

拷贝初始化的限制

/**
拷贝初始化的限制
*/
void fun2()
{
    vector<int> v1(10);     //正确:直接初始化
//    vector<int> v2=10;      //错误:接受大小参数的构造函数式explicit的
    void f(vector<int>);    //f的参数进行拷贝初始化
//    f(10);                  //错误:不能用一个explicit的构造函数拷贝一个实参
//    f(vector<int>(10));     //正确:从一个int直接构造一个临时的vector
}

13.1.2拷贝赋值运算符

/**************************************
13.1.2拷贝赋值运算符
**************************************/
void fun3()
{
    Sales_data trans, accum;
    trans=accum;        //使用Sales_data的拷贝赋值运算符
}

重载赋值运算符

/**
重载赋值运算符
*/

class Foo2
{
public:
    Foo2& operator=(const Foo2&);     //赋值运算符
    //...
};

合成拷贝赋值运算符

/**
合成拷贝赋值运算符
*/
Sales_data&
Sales_data::operator=(const Sales_data &rhs)
{
    bookNo=rhs.bookNo;      //调用string::operator=
    units_sold=rhs.units_sold;  //使用内置的int赋值
    revenue=rhs.revenue;        //使用内置的double赋值
    return *this;               //返回一个此对象的引用
}

13.1.3析构函数

/**************************************
13.1.3析构函数
**************************************/
class Foo3
{
public:
    ~Foo3();     //析构函数
    //...
};

析构函数自动运行,我们的程序可以按需要分配资源,无需担心何时释放这些资源
void fun4()
{
    //p和p2指向动态分配的对象
    Sales_data *p=new Sales_data;       //p是一个内置指针
    auto p2=shared_ptr<Sales_data>();   //p2是一个shared_ptr
    Sales_data item(*p);        //拷贝构造函数吧*p拷贝到item中
    vector<Sales_data> vec;     //局部对象
    vec.push_back(*p2);         //拷贝p2指向的对象
    delete p;                   //对p指向的对象执行析构函数
}
//退出局部作用域;对item,vec,p2调用析构函数
//销毁p2会递减其引用计数;如果引用计数变为0,对象被释放
//销毁vec会销毁它的元素

FOO类

//Foo类
class Foo4
{
public:
    Foo4(){cout<<"想知道我为何这么屌?"<<endl;}      //默认构造函数
    Foo4(const Foo4&);    //拷贝构造函数
    Foo4& operator=(const Foo4&);     //赋值运算符
    ~Foo4(){cout<<"cutter_point:我就是这么屌!";}                //析构函数
};

Foo4& Foo4::operator=(const Foo4 &f)
{
    cout<<"你为何这么屌cutter_point?";
}

全代码!!!

/**
* 功能:拷贝、赋值与销毁
* 时间:2014年7月11日09:39:06
* 作者:cutter_point
*/

#include<iostream>
#include<string>
#include<vector>
#include<memory>

using namespace std;

/**************************************
13.1.1拷贝构造函数
**************************************/

class Foo1
{
public:
    Foo1();              //默认构造函数
    Foo1(const Foo1&);    //拷贝构造函数
    //...
};

/*
拷贝构造函数的第一个参数必须是一个参数
*/

/**************************************
合成拷贝构造函数
**************************************/
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:
	// constructors
	Sales_data(): units_sold(0), revenue(0.0) { }
	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(const Sales_data&);
    Sales_data& operator=(const Sales_data&);   //赋值运算符
    ~Sales_data(){}
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();
}

/**************************************
拷贝初始化
**************************************/
void fun1()
{
    string dots(10, '.');   //直接初始化
    string s(dots);         //直接初始化
    string s2=dots;         //拷贝初始化
    string null_book="9-999-99999-9";   //拷贝初始化
    string nines=string(100, '9');      //拷贝初始化
}
/*
拷贝初始化不仅在我们用=定义变量时会发生,在下列情况下也会发生
*将一个对象作为实参传递给一个非引用类型的形参
*从一个返回类型为非引用类型的函数返回一个对象
*用花括号列表初始化一个数组中的元素或一个聚合类中的成员
*/

/**
拷贝初始化的限制
*/
void fun2()
{
    vector<int> v1(10);     //正确:直接初始化
//    vector<int> v2=10;      //错误:接受大小参数的构造函数式explicit的
    void f(vector<int>);    //f的参数进行拷贝初始化
//    f(10);                  //错误:不能用一个explicit的构造函数拷贝一个实参
//    f(vector<int>(10));     //正确:从一个int直接构造一个临时的vector
}

/**************************************
13.1.2拷贝赋值运算符
**************************************/
void fun3()
{
    Sales_data trans, accum;
    trans=accum;        //使用Sales_data的拷贝赋值运算符
}

/**
重载赋值运算符
*/

class Foo2
{
public:
    Foo2& operator=(const Foo2&);     //赋值运算符
    //...
};

/**
合成拷贝赋值运算符
*/
Sales_data&
Sales_data::operator=(const Sales_data &rhs)
{
    bookNo=rhs.bookNo;      //调用string::operator=
    units_sold=rhs.units_sold;  //使用内置的int赋值
    revenue=rhs.revenue;        //使用内置的double赋值
    return *this;               //返回一个此对象的引用
}

/**************************************
13.1.3析构函数
**************************************/
class Foo3
{
public:
    ~Foo3();     //析构函数
    //...
};


/*
析构函数自动运行,我们的程序可以按需要分配资源,无需担心何时释放这些资源
*/
void fun4()
{
    //p和p2指向动态分配的对象
    Sales_data *p=new Sales_data;       //p是一个内置指针
    auto p2=shared_ptr<Sales_data>();   //p2是一个shared_ptr
    Sales_data item(*p);        //拷贝构造函数吧*p拷贝到item中
    vector<Sales_data> vec;     //局部对象
    vec.push_back(*p2);         //拷贝p2指向的对象
    delete p;                   //对p指向的对象执行析构函数
}
//退出局部作用域;对item,vec,p2调用析构函数
//销毁p2会递减其引用计数;如果引用计数变为0,对象被释放
//销毁vec会销毁它的元素


//Foo类
class Foo4
{
public:
    Foo4(){cout<<"想知道我为何这么屌?"<<endl;}      //默认构造函数
    Foo4(const Foo4&);    //拷贝构造函数
    Foo4& operator=(const Foo4&);     //赋值运算符
    ~Foo4(){cout<<"cutter_point:我就是这么屌!";}                //析构函数
};

Foo4& Foo4::operator=(const Foo4 &f)
{
    cout<<"你为何这么屌cutter_point?";
}


int main()
{
    Foo4 *f4=new Foo4();
    delete f4;
    return 0;
}

结果图!!(新产品)




PS:尼玛,完全没法淡定了,大热天的感冒,我的天,我受不了了。。。。。。。。。。。。抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂抓狂