解释
类默认函数的控制
程序员只需在函数声明后加上“=default;
”,就可将该函数声明为 "=default
"函数,编译器将为显式声明的 "=default
"函数自动生成函数体,因为必须要有一个构造函数有函数体。
程序员只需在函数声明后上“=delete;
”,就可将该函数禁用。
=default 声明函数为默认构造函数
=delete 禁用该函数
样例
#ifdef _CV_H
#define _CV_H
class cv{
cv(const cv&) = delete;
cv& operator=(const cv&) = delete;
cv(cv&&);
cv& operator=(cv&&);
};
#endif
在C++03的标准里面,如果程序代码里面没有写默认构造函数(像cv();
)复制构造函数、复制赋值函数(像cv cv2=cv1;
)和析构函数,则编译器会自动添加这些函数。当程序里面写了构造函数的时候,编译器就不会自动添加默认构造函数了。
那如果我想让一个类的实例不能通过复制构造函数来生成,该怎么办呢?一般的方法是将复制构造函数和复制赋值函数声明为private,而且不去具体实现它们,这样就达到了目的。
但这样做其实是很tricky的方式,相当于利用c++的一些特性碰巧来实现,总感觉不是正确的方法。
C++11里面可以用default来指定使用默认的构造函数,而且可以通过delete来显式地禁止一些方法,如复制构造函数和复制赋值操作,如下例:
struct NonCopyable{
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
};
这个例子里面,第一条语句是强制编译器生成默认构造函数作为struct的构造函数;第2、3条语句就是显式地禁用复制构造函数和复制赋值函数。
既然禁止了复制构造函数,那么如果想通过已经生成的类的实例来初始化一个同类的实例,要怎么操作呢?显然,cv cv2(cv1)
和cv cv2=cv1;
是不可以用的了,因为复制构造函数已经被禁止了。
C++11新定义了一个叫做move constructor
的构造函数,签名方法如下:
class_name(class_name &&);
class_name& operator=(class_name &&);
调用时:
class_name c1;
class_name c2=std::move(c1);
class_name c3(std:move(c1));
所谓move
,我的理解就是类似于指针一样的概念,move
生成的新的实例和原先的实例是由同一个指针指向的,即实际上是同一个实例。而且&&
这个符号让人联想到了**
,可能也是这个意思吧。