c++新特性之default,delete

用法

=default 表示使用编译器为我们提供的实现,=delete表示删除函数,不实现。

=default =delete一般只能用在编译器为我们生成的函数上,比如构造函数,拷贝构造,析沟函数(不要使用=delete),赋值等。

=delete可以用在普通成员函数,但是没有意义。=delete修饰析构函数时,无法进行释放对象,因此无法生成临时变量,无法进行delete,也无法当作父类。

下面进行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct Complex
{
int real,image;
Complex(int a, int b=0) : real(a), image(b)
{
}
void print() = delete; //oK
//void print2() = default; //errror
~Complex()=delete;
};

int main()
{
//Complex c; //error
Complex *s = new Complex(12, 5);
//s->print(); //error
// delete s;//error
return 0;
}

在c++11之前如果我们自行定义了一个构造函数,那么编译器就不会生成一个默认的构造函数。
在c++11中我们可以加上=default,获得并使用默认的构造函数。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
class zoo 
{
public:
Zoo(int i1,int i2):d1(i1),d2(i2){}
Zoo() = default;
Zoo(const Zoo&) = delete;
Zoo(Zoo&&) = default;
Zoo& operator=(const Zoo&)=default;
Zoo& operator=(const Zoo&&)= delete;
virtual ~Zoo(){}
private:
int d1,d2;
}

其他

空类什么时候不空?

我们定义一个空类,编译器就会为它声明一个拷贝构造,一个拷贝赋值,和析构,构造函数。这些函数都是public且inline.

1
class Empty{};

我们定义了Empty,当我们没有调用构造,析构等函数时,编译器是不会给我们合成的。

唯有这些函数被调用时,它们才会被编译器合成。

1
2
3
4
5
{
Empty e1; //调用了构造析构
Empty e2(e1);//拷贝构造析构
e2 = e1;//拷贝赋值
}

常见用法noCopy

将拷贝相关的代码delete,实现nocopy 功能
M

1
2
3
4
5
6
7
8
class NoCopy
{
public:
NoCopy() = default;
NoCopy(const NoCopy&)=delete;
NoCopy& operator=(const NoCopy&)=delete;
~NoCopy() = default;
}

当我们需要实现这个功能时只需要继承 NoCopy就可以了。

当然实现NoCopy还有其他方式,将拷贝构造,拷贝赋值的属性变为private。这种方式对于友元是无效的。

如下是boost::noncopyable实现。

1
2
3
4
5
6
7
8
9
class noncopyable
{
protected:
noncopyable(){}
~noncopyable(){}
private:
noncopyable(const noncopyable&){}
const noncopyable& operator=(const noncopyable&){}
}