定义一个类,就要显式或隐式定义此对象的拷贝,移动,赋值与销毁:
- 拷贝构造函数
- 拷贝赋值运算符
- 移动构造函数
- 移动赋值运算符
- 析构函数
拷贝构造函数:参数是自身类类型的引用
class Foo{
Foo();
Foo(const Foo &);
}
如果没有自己定义拷贝构造函数,编译器会定义一个,与合成默认构造函数不同。即使有其他构造函数,编译器也会合成一个拷贝构造函数。拷贝构造函数是使用同一类中之前创建的对象来初始化新创建的对象
string s(10,'.') or string s(s1): 直接初始化
string s=s1; :拷贝初始化
A x(2); //直接初始化,调用构造函数
A y = x; //拷贝初始化,调用拷贝构造函数
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
一个对象以值传递的方式传入函数体
一个对象以值传递的方式从函数返回
一个对象需要通过另外一个对象进行初始化。
#include <iostream> using namespace std; class Line{ public: int getLength(); Line(int len); Line(const Line & obj); ~Line(); private: int * ptr; }; Line :: Line(int len) { cout<<"调用构造函数"<<endl; ptr=new int; * ptr=len; } Line :: Line(const Line & obj) { cout<<"调用拷贝构造函数并为指针ptr 分配内存"<<endl; ptr=new int; ptr= obj.ptr;//拷贝 } Line :: ~ Line(void) { cout<<"释放内存"<<endl; delete ptr; } Line :: getLength() { return * ptr; } void display(Line obj) { cout<<"line 大小"<< obj.getLength()<<endl; }
拷贝赋值运算符:
Sales_data trans, accum;
trans=accum;// 使用Sales_data 的拷贝赋值运算符,
和拷贝构造函数一样,如果类未定义自己的拷贝赋值运算符,编译器会合成一个。
重载赋值运算符:函数,名字由operator 关键字后接表示要定义的运算符的符号组成。赋值运算符就是名为operator= 的函数。
左侧运算对象绑定到隐式的this 参数。 右侧运算对象作为显式参数传递。
class Foo{
public:
Foo & operator=(const Foo&);// 赋值运算符
}
与内置类型的赋值一致,赋值运算返回一个指向其左侧运算对象的引用。
析构函数:
析构函数与构造函数相反的操作,构造函数初始化对象的非static 数据成员,构析函数释放对象使用的资源并销毁非static数据成员。
没有返回值,不接受参数。如果未定义自己的构析函数,编译器会定义一个合成构析函数。 阻止对象被销毁。。
重载运算符:
定义重载运算符,决定定义为类的成员函数或声明为一个普通的非成员函数。
- =, [], () ,-> 必须为成员 += -= 成员
- --,++ 成员 , 解引用 * 成员
- 算术,相等性,关系等,非成员
当定义为成员函数时, 左侧运算符所属类的一个对象。
string s="t"+s; 错误
输入输出符重载:
输出<<, 一个形参是一个非常量ostream 对象的引用。ostream 非常量因为向流中写入会改变状态。 而且该型参是引用因为无法直接复制一个ostream对象。第二个形参是常量的引用, 该常量形参是要打印类类型。第二个形参是引用是因为我们要复制实参。
ostream & operator <<(ostream & os, const Sales_data & item) { os<< item.isbn()<<" "<<item.units_sold<<" "<< item.revenue<< " "<<endl return os; }
运算符返回ostream的引用。
输入输出运算符必须是非成员函数, 否则,左侧运算对象时类的对象:
Sales_data data;
data<< cout<<;
必须是istream 类型,或ostream
istream & operator>>(istream & is, Sales_data & item) { is >> item.bookNo>> item.units_sold>> price; if( is) item.revenue=item.units_sold* price; else item=Sales_data();//输入失败,为默认状态 return is }
复制运算符:
class strvec{
public:
strvec & operator= (initializer_list<string>);
}
strvec & strvec:: operator=(initalizer_list<string> l)
{
//分配空间
auto data=alloc_n_copy(l.begin(),l.end());
free();
elements=data.first;
first_free=cap=data.second;
return * this;
}
下标运算符: