好久没写博客了,博客荒废了,人也废了,c++ primer果然经典,看了之后明白了许多之前不懂得细节。
当定义一个新类型的时候,需要显示或隐式地指定复制,赋值和撤销该类型的对象时会发生什么---这是通过定义特殊成员:复制构造函数、赋值操作符重载和析构函数来达到的。如果没有显示定义这些,编译器会为我们实现。
之前学习c++语言时大家知道函数参数传递方式有两种,值传递和引用传递。值传递开始自己理解为就是拷贝,但是执行的是什么拷贝?=号函数还是拷贝构造函数,答案是拷贝构造函数。函数返回值时编译器会创造一个临时变量,执行的也是拷贝构造函数。
View Code
#include <iostream> class Point{ private: int x; int y; public: Point(std::istream &is){ is>>x>>y; } Point(int _x=0,int _y=0):x(_x),y(_y){} Point(const Point &pt){ std::cout<<"in Point(const Point &pt) function!"<<std::endl; x=pt.x; y=pt.y; } Point& operator=(const Point &pt){ std::cout<<"in operator= function!"<<std::endl; x=pt.x; y=pt.y; } void Print(){ std::cout<<"x="<<x<<",y="<<y<<std::endl; } }; Point global; Point foo_bar(Point arg){ std::cout<<"in foo_bar!"<<std::endl; std::cout<<"Point local=arg"<<std::endl; Point local=arg; std::cout<<"Point *heap=new Point(global)"<<std::endl; Point *heap=new Point(global); std::cout<<"*heap=local"<<std::endl; *heap=local; return *heap; } int main(void){ std::cout<<"in main!"<<std::endl; Point pt(2,3); std::cout<<"Point test=foo_bar(pt)"<<std::endl; Point test=foo_bar(pt); test.Print(); test=std::cin; test.Print(); return 0; }
结果截图:
可以看到函数形参传递,返回值执行的都是拷贝构造函数。=号操作符函数什么时候执行呢,答案是=号左边对象早已存在时执行,否则依旧执行拷贝构造函数。
另外c++ 中的explicit 关键字可以限制编译器的隐式转换,据说是为了兼容c的语法,函数传参时,形参类型和实参不一致,会对实参执行一个形参类型的构造函数,这个构造函数以这个形参为参数。
上列中的test=std::cin 就是这样转换的:
1.编译器创建无名对象=Point(std::cin)
2.test=无名对象
就是这么一个结果。