1. c++自动提供了以下的成员函数
默认构造函数,如果没有定义构造函数
默认析构函数,如果没有定义
复制构造函数,如果没有定义,java参见:https://blog.csdn.net/ShewMi/article/details/80788591
赋值运算符,如果没有定义
地址运算符,如果没有定义
移动构造函数
移动赋值运算符
a. 默认构造函数
编译器在没有提供构造函数时候,编译器将提供一个不接受任何参数,也不执行任何操作的构造函数
如果定义了构造函数,编译器将不提供任何默认构造函数,如果希望创建对象时不显示的对它进行初始化,则必须显示定义默认构造函数,这种构造函数没有任何参数,但是可以使用它来设置特定的值
b. 复制构造函数
复制构造函数用于将一个对象复制到一个新创建的对象中,也就是说,它用于初始化过程中,而不是常规的赋值过程中
调用的时机:
当函数的参数为类对象的时候
函数的返回值是类对象
对象需要另一个对象进行初始化
由于按值传递对象将调用赋值构造函数,因此应该使用按引用传递对象,这样可以节省调用构造函数的时间以及存储新对象的空间。
默认赋值构造函数的功能:逐个赋值非静态成员(成员赋值也称浅赋值),赋值的是成员的值,如果类中存在一个静态的对象计数变量,默认的复制构造函数不说明其行为,也不增加计数器的个数,但是析构函数会更新次数,解决方法是提供一个对计数进行更新的显示复制构造函数
如果对象中存在指针变量,默认的复制构造函数将不会为该指针分配空间,复制时候会将原对象和复制对象的指针指向同一个位置,析构两个对象会对同一个指针delete两次,从而会出现严重的问题。
警告:如果类中包含了使用new 初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,这称为深度复制。复制的另一种形式(成员复制或者浅复制)只是复制指针值,浅复制仅浅浅复制指针的信息,而不会深入挖掘以复制指针引用的结构
赋值构造函数本质是构造函数,所以可以按照下面方式显式调用:
c. 赋值运算符:
String knot;
String metoo = knot; // 调用的拷贝构造函数
String youtoo;
youtoo = knot; // 调用赋值运算符重载
默认的赋值运算符隐式实现也是对成员进行逐个赋值,如果成员本身就是类对象,则程序将使用这个类定义的赋值运算符来复制这个成员,静态数据成员不受影响。
注意:由于目标对象可能以及引用了以前分配的数据,所以函数应该使用delete[] 来释放这些数据
函数应当避免将对象赋值给自身,否则,在给对象重新赋值之前,释放内存操作可能会删除对象的内容。
函数返回一个指向调用对象的引用,通过返回一个对象,函数可以像赋值常规操作那样,连续进行赋值
d. 默认析构函数:
如果类中有使用new的指针成员变量,析构函数是必不可少的,此外,析构函数一般被定义为virtual,这是为了重载以后被重载的类也能够正常的释放内存
例:String类
#include <iostream> using namespace std; class String { private: char* str; int len; static int num_strings; static const int CINLIM = 80; // static 修饰的常量在类中初始化 public: // constructors and other methods String(); String(const char*); String(const String&); ~String(); int length() const { return len; } // overloaded operator methods String& operator=(const String &); String& operator=(const char *); char& operator[](int); const char& operator[](int) const; // overloaded operator friends friend bool operator<(const String&, const String&); friend bool operator>(const String&, const String&); friend bool operator==(const String&, const String&); friend ostream& operator<<(ostream&, const String&); friend istream& operator>>(istream&, String&); // static function static int howMany(); };
#include "String.h" #include <cstring> #include <iostream> using namespace std; #pragma warning(disable:4996) int String::num_strings = 0; int String::howMany() { return num_strings; } String::String(const char* s) { len = strlen(s); str = new char[len + 1]; strcpy(str, s); num_strings++; } String::String() { len = 0; str = new char[1]; str[0] = '