在c++中,当我们定义一个类的时候,如果我们什么都不定义的时候,c++编译器会默认的为我们生成一些函数。
例如定义一个Example类。
class Example{
};
当我们定义一个Example类的时候,不定义任何操作的时候,c++编译系统将为Example类生成如下默认操作函数:
1. 默认构造函数Example();
2. 拷贝构造函数Example(const Example&);
3. 拷贝赋值函数Example & operator=(const Example &);
4. 移动构造函数Example(Example &&);
5. 析构函数~Example();
默认的为程序提供这些操作,但是coder可以通过声明这些函数中一个或几个操作,获取相关函数的控制权。将相关默认构造函数、拷贝构造函数、拷贝赋值函数、move构造函 数、析构函数,换成自己的定义,但是与之相关的操作(编译器定义的)将被禁止使用。
规则如下:
1. 如果coder为类定义了构造函数,不管是拷贝构造函数还是带参数的构造函数,则编译器为类生成的默认构造函数将被禁止使用。
2. 如果coder为类定义了拷贝构造函数或者拷贝赋值函数、move构造函数、析构函数,则编译器为类自动生成的拷贝构造函数、拷贝赋值函数、move构造函数、析构函数将被 禁止,也就是编译器不在为那个类生成默认的拷贝构造函数、拷贝赋值函数、move构造函数、析构函数。但是实际上,由于向后兼容的需求,即使析构函数被定义,默认的 拷贝构造函数以及默认的拷贝赋值函数也会被编译器默认生成。
针对第一个规则,声明一个类定义如下:
class Example{
public:
Example(int a);
private:
int a;
};
Example::Example(int a){
this->a = a;
}
在main函数中插入如下语句,Example tmp;发现编译器报错,说没有构造函数。也由此证明了规则1的成立。
针对规则2,声明一个类如下:
class Example{
public:
~Example();
private:
int a;
};
Example::~Example()
{
printf("destructor");
}
在main函数中定义:
Example a, b;
a = b;
编译通过,正确运行。
例外举一个定义了move构造函数、不带参数的构造函数,编译器不会生成默认的拷贝构造函数;
class Example{
public:
Example(){}
Example(Example&& tmp);
private:
int a;
};
Example::Example(Example&& tmp)
{
printf("move");
}
Example tmp1;
Example tmp2;
tmp1 = tmp2;// 报错,没有copy构造
因为构造函数的相互影响,如果定义其中一个构造函数,而其他构造函数想使用默认的,则可以通过将声明构造函数后=default。例子如下:
-
-
-
class gslice {
public:
gslice() = default;̃gslice() = default;
gslice(const gslice&) = default;};
-
gslice(gslice&&) = default;
gslice& operator=(const gslice&) = default; -
gslice& operator=(gslice&&) = default;
-
// ...};
-
这段代码等价于:
-
class gslice {
-
valarray<size_t> size;valarray<size_t> stride;valarray<size_t> d1;
-
};