前言本篇将对上篇的拷贝构造函数进行补充说明和对赋值运算符,取地址运算符重载进行梳理.拷贝构造函数:下列三种拷贝构造函数的写法哪个是错的?class Data { public: Data (int year 1 , int month 1 , int day 1) { _year year; _month month; _day day; } //拷贝构造 Data (Data d) { _year d._year; _month d._month; _day d._day; } Data (Data d) { _year d._year; _month d._month; _day d._day; } Data (Data* d) { _year d-_year; _month d-_month; _day d-_day; } private: int _year 0; int _month 0; int _day 0; };结论是中间的拷贝构造写法会报编译错误下面来介绍它在用法上的细节:1.#includeiostream using namespace std; class Data { public: Data (int year 1 , int month 1 , int day 1) { _year year; _month month; _day day; } //拷贝构造 Data (const Data d) { _year d._year; _month d._month; _day d._day; cout copy endl; } Data (Data* d) { _year d-_year; _month d-_month; _day d-_day; } void Print () { cout _year - _month - _day endl; } private: int _year 0; int _month 0; int _day 0; }; void test1 (Data d) { cout d endl; d.Print (); } int main () { Data d1(2026 , 6 , 12); // C规定自定义类型对象进行拷贝行为必须调用拷贝构造所以这里传值传参要调用拷贝 //所以这里的d1传值传参给d要调用拷贝构造完成拷贝传引用传参可以较少这里的拷贝 test1 (d1); //这不是一个拷贝构造,只是一次普通的构造函数 Data d2(d1); d2.Print (); //这样才是,通过同类型的对象去初始化 Data d3 (d1); d3.Print (); //这样也行 Data d4 d1; d4.Print (); return 0; }运行结果:2.#includeiostream using namespace std; class Data { public: Data (int year 1 , int month 1 , int day 1) { _year year; _month month; _day day; } //拷贝构造 Data (const Data d) { _year d._year; _month d._month; _day d._day; cout copy endl; } Data (Data* d) { _year d-_year; _month d-_month; _day d-_day; } void Print () { cout _year - _month - _day endl; } private: int _year 0; int _month 0; int _day 0; }; Data test2 () { Data tmp (2026 , 6 , 12); tmp.Print (); return tmp; } int main () { Data d1 test2 (); d1.Print (); return 0; }运行结果:但.....这里有问题,这里的问题是tmp是函数里边的变量,会随着函数的销毁而跟着销毁,从而会产生一种野引用的错误,现在输出结果没有错的原因是因为函数栈帧资源还没来得及随着函数栈帧空间销毁.但我们在中间加上一点输出运行结果:由此可见,在返回函数的变量时要注意这个变量会不会随着空间销毁而销毁.赋值运算符重载:赋值运算符重载是一个默认成员函数,这里得和拷贝构造函数区分一下,拷贝构造函数是将一个对象去对另外一个要创建的对象进行初始化,而赋值运算符重载是两个已经存在的对象进行直接的拷贝,以下是一些需要注意的细节:1.赋值运算符重载是一个运算符重载,是一个运算符重载,规定必须重载为成员函数,其参数建议写成const当前类类型的引用,否则传值传参会有拷贝.运算符重载在此之前,先来介绍下运算符重载:1.类类型在计算的时候,必须转换成调用对应的运算符进行重载2.运算符重载其实是具有特殊名字的函数,是名字由operator后面的所要重载的运算符组成,它也和普通函数一样,拥有返回类型和参数列表.3.重载运算符函数的参数个数和运算符作用的对象一样多(例如重载,就拥有两个参数)4.如果重载运算符函数是成员函数的话,那么它的第一个参数默认传给隐式的this指针,所以参数列表就会比运算对象少一个.5.重载以后优先级和结合性应该符合对应的运算符的原则6.不能链接语法中没有的符号(例如:operator)7..* :: sizeof ?: .这五个不能重载8.重载操作符至少要有一个类类型的参数对象9.重载时,规定后置比前置要多一个形参intDate operator() { cout 前置 endl; //... return *this; } Date operator(int) { Date tmp; cout 后置 endl; //... return tmp; }10.重载和时需要重载为全局函数因为重载为成员函数this指针默认抢占了第⼀个形参位置第⼀个形参位置是左侧运算对象调用时就变成了对象cout不符合使用习惯和可读性。 重载为全局函数把ostream/istream放到第⼀个形参位置就可以了第⼆个形参位置当类类型对象。现在,让我们回到赋值运算符重载,赋值运算符重载被规定成必须是成员函数,且其参数建议写成const类类型的引用,否则传值传参会有拷贝返回值:返回值建议写成类类型的引用,因为引用返回可以提高效率,方便连续赋值若并不需要资源消耗的赋值运算符,我们可以让系统自己生成,当然这是浅拷贝的.