【脚印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;
}

结果图!!(新产品)

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


PS:尼玛,完全没法淡定了,大热天的感冒,我的天,我受不了了。。。。。。。。。。。。【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)【脚印C++primer】42、拷贝、赋值与销毁(1)