服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

香港云服务器
服务器之家 - 编程语言 - C/C++ - C++11新特性“=default”,“=delete”的使用

C++11新特性“=default”,“=delete”的使用

2021-11-09 13:29君子黎 C/C++

=default、=delete 是C++11的新特性,分别为:显式缺省(告知编译器生成函数默认的缺省版本)和显式删除(告知编译器不生成函数默认的缺省版本),本文就来介绍一下如何使用

1、 =default 和=delete 概述

任何事物的出现都必然有着其出现的理由,伴随着每一个新的概念产生都会带来一系列的便利和价值。C++在不断的演变与发展,与此同时,伴随着许多新的特性和功能产生。=default、=delete 是C++11的新特性,分别为:显式缺省(告知编译器生成函数默认的缺省版本)和显式删除(告知编译器不生成函数默认的缺省版本)。C++11中引进这两种新特性的目的是为了增强对“类默认函数的控制”,从而让程序员更加精准地去控制默认版本的函数。其具体的功能和使用方法下面将一一道来。

2、 类与默认函数

在讲解关键字 default和delete 之前,先对类和类的默认函数作下描述与说明,从而加深对这两个关键字的理解与认知。既要知其然,也要知其所以然。C++中,当我们设计与编写一个类时,若不显著写明,则类会默认为我们提供如下几个函数:

(1)构造函数
(2)析构函数
(3)拷贝构造函数
(4)拷贝赋值函数(operator=)
(5)移动构造函数
以及全局的默认操作符函数:
(1)operator,
(2)operator &
(3)operator &&
(4)operator *
(5)operator->
(6)operator->*
(7)operator new
(8)operator delete

注:若我们在类中实现了这些版本之后,编译器便不会生成其对应的默认函数版本,这时需要我们显式的写上其对应的默认函数版本。

如例1所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*************************************************************************
 * File Name: Student.cpp
 * Author:    The answer
 * Function:  Other       
 * Mail:      2412799512@qq.com
 * Created Time: 2018年07月17日 星期二 23时08分20秒
 ************************************************************************/
 
#include<iostream>
using namespace std;
class Student
{
public:
    Student(const int a,const int b)
        :m_a(a)
        ,m_b(b)
    {
 
    }
 
int getA()const{return m_a;}
int getB()const{return m_b;}
private:
int m_a;
int m_b;
};
 
int main(int argc,char **argv)
{
Student stu(1,2);
cout<<stu.getA()<<endl; //1
cout<<stu.getB()<<endl; //2
 
    Student stu1;           //编译失败,报错: no matching function for call to ‘Student::Student()'
 
return 0;
}

编译方式:g++ Student.cpp

编译报错,提示:Student.cpp: In function ‘int main(int, char**)':
Student.cpp:34:13: error: no matching function for call to ‘Student::Student()'
Student stu1;

例1定义了一个对象stu1,该对象将会使用Student类的无参构造函数,而该默认构造函数在Student类中,我们没有显式的说明。因此,c++编译器在我们提供了该函数实现之后是不会生成与之对应的默认函数版本的。在Student中我们重载了带2个参数的构造函数,但是无参的构造函数,没有提供,因此会报错。

解决方式是:在该类中显式的提供无参构造函数,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*************************************************************************
 * File Name: Student.cpp
 * Author:    The answer
 * Function:  Other       
 * Mail:      2412799512@qq.com
 * Created Time: 2018年07月17日 星期二 23时08分20秒
 ************************************************************************/
 
#include<iostream>
using namespace std;
class Student
{
public:
    Student(){}   //显式说明Student的无参构造函数
    Student(const int a,const int b)
        :m_a(a)
        ,m_b(b)
    {
 
    }
 
int getA()const{return m_a;}
int getB()const{return m_b;}
private:
int m_a;
int m_b;
};
 
int main(int argc,char **argv)
{
Student stu(1,2);
cout<<stu.getA()<<endl; //1
cout<<stu.getB()<<endl; //2
 
    Student stu1;
return 0;
}

问题:以 Student(){} 这样的方式来声明无参数构造函数,会带来一个问题,就是使得 其不再是 POD 类型,因此可能让编译器失去对这样的数据类型的优化功能。这是我们不希望看到的。因此最好使用 = default来修饰默认构造函数。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*************************************************************************
 * File Name: Student.cpp
 * Author:    The answer
 * Function:  Other       
 * Mail:      2412799512@qq.com
 * Created Time: 2018年07月17日 星期二 23时08分20秒
 ************************************************************************/
 
#include<iostream>
using namespace std;
class Student
{
public:
    Student() = default;
    Student(const int a,const int b)
        :m_a(a)
        ,m_b(b)
    {
 
    }
 
int getA()const{return m_a;}
int getB()const{return m_b;}
private:
int m_a;
int m_b;
};
 
int main(int argc,char **argv)
{
Student stu(1,2);
cout<<stu.getA()<<endl; //1
cout<<stu.getB()<<endl; //2
 
    Student stu1;
 
//使用is_pod模板类可以查看某类型是否属于POD类型,若为POD类型,则返回1,反之,返回0
std::cout<<is_pod<Student>::value<<std::endl;  //1
return 0;
}

更多关于is_pod的用法请参考: std::is_pod 。

3、 使用“=delete”来限制函数生成

C++开发中,我们经常需要控制某些函数的生成。在C++11之前,我们经常的普遍做法是将其声明为类的 private 成员函数,这样若在类外这些这些函数的操作时候,编译器便会报错,从而达到效果。如例2:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*************************************************************************
 * File Name: Student.cpp
 * Author:    The answer
 * Function:  Other       
 * Mail:      2412799512@qq.com
 * Created Time: 2018年07月17日 星期二 23时08分20秒
 ************************************************************************/
 
#include<iostream>
using namespace std;
class Student
{
public:
    Student() = default;
    Student(const int a,const int b)
        :m_a(a)
        ,m_b(b)
    {
 
    }
 
int getA()const{return m_a;}
int getB()const{return m_b;}
 
private:
    Student(const Student& );
    Student& operator =(const Student& );
 
private:
int m_a;
int m_b;
};
 
int main(int argc,char **argv)
{
Student stu(1,2);
cout<<stu.getA()<<endl; //1
cout<<stu.getB()<<endl; //2
 
//Student stu1(stu);
//报错:Student.cpp:26:5: error: ‘Student::Student(const Student&)' is private
 
 
//Student stu1(3,4);
//stu1 = stu;
//报错:Student.cpp:27:14: error: ‘Student& Student::operator=(const Student&)' is private
 
std::cout<<is_pod<Student>::value<<std::endl;  //
return 0;
}

例2代码编译报错,因为在类中,我们将Student的拷贝构造函数和拷贝赋值函数都声明为了 private 属性,因此,当在类外使用拷贝构造和拷贝赋值操作值,编译器会报错。虽然能够达到效果,但是不够直观和简洁。对于追求高效以及简洁来说,这样做有2个问题:

(1)不是最简化;
(2)对于友元支持不友好.

更为简洁直观的方法是使用:=delete

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/************************************************************************
 * Author:    The answer
 * Function:  Other       
 * Mail:      2412799512@qq.com
 * Created Time: 2018年07月17日 星期二 23时08分20秒
 ************************************************************************/
 
#include<iostream>
using namespace std;
class Student
{
public:
    Student() = default;
    Student(const int a,const int b)
        :m_a(a)
        ,m_b(b)
    {
 
    }
 
int getA()const{return m_a;}
int getB()const{return m_b;}
 
    Student(const Student& ) = delete;
    Student& operator =(const Student& ) = delete;
 
private:
int m_a;
int m_b;
};
 
int main(int argc,char **argv)
{
Student stu(1,2);
cout<<stu.getA()<<endl; //1
cout<<stu.getB()<<endl; //2
 
//Student stu1(stu);
//报错:Student.cpp:39:21: error: use of deleted function ‘Student::Student(const Student&)'
 
//Student(const Student& );
 
//Student stu1(3,4);
//stu1 = stu;
//报错:SStudent.cpp:44:10: error: use of deleted function ‘Student& Student::operator=(const Student&)'
 
std::cout<<is_pod<Student>::value<<std::endl;  //
return 0;
}

注:若缺省版本被删除了,重载该函数是非法的.

4、 “=default”使用范围

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
"=default"不仅仅局限于类的定义内,也可以用于类的定义外来修饰成员函数,如例3:
/*************************************************************************
 * File Name: Student.cpp
 * Author:    The answer
 * Function:  Other       
 * Mail:      2412799512@qq.com
 * Created Time: 2018年07月17日 星期二 23时08分20秒
 ************************************************************************/
 
#include<iostream>
using namespace std;
class Student
{
public:
    Student() = default;
    Student(const int a,const int b)
        :m_a(a)
        ,m_b(b)
    {
 
    }
 
int getA()const{return m_a;}
int getB()const{return m_b;}
 
    Student(const Student& ) = delete;
    Student& operator=(const Student& );
 
private:
int m_a;
int m_b;
};
 
 Student& Student::operator =(const Student& ) = delete;
 
int main(int argc,char **argv)
{
Student stu(1,2);
cout<<stu.getA()<<endl; //1
cout<<stu.getB()<<endl; //2
 
Student stu1(3,4);
    stu1 = stu;
//编译报错:Student.cpp:42:10: error: use of deleted function ‘Student& Student::operator=(const Student&)'
 
std::cout<<is_pod<Student>::value<<std::endl;  //
return 0;
}

到此这篇关于C++11新特性“=default”,“=delete”的使用的文章就介绍到这了,更多相关C++11 =default =delete内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家! 

原文链接:https://juejin.cn/post/6965388048372596743

延伸 · 阅读

精彩推荐
  • C/C++C语言实现电脑关机程序

    C语言实现电脑关机程序

    这篇文章主要为大家详细介绍了C语言实现电脑关机程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    xiaocaidayong8482021-08-20
  • C/C++深入理解goto语句的替代实现方式分析

    深入理解goto语句的替代实现方式分析

    本篇文章是对goto语句的替代实现方式进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网7342020-12-03
  • C/C++详解c语言中的 strcpy和strncpy字符串函数使用

    详解c语言中的 strcpy和strncpy字符串函数使用

    strcpy 和strcnpy函数是字符串复制函数。接下来通过本文给大家介绍c语言中的strcpy和strncpy字符串函数使用,感兴趣的朋友跟随小编要求看看吧...

    spring-go5642021-07-02
  • C/C++学习C++编程的必备软件

    学习C++编程的必备软件

    本文给大家分享的是作者在学习使用C++进行编程的时候所用到的一些常用的软件,这里推荐给大家...

    谢恩铭10102021-05-08
  • C/C++C++之重载 重定义与重写用法详解

    C++之重载 重定义与重写用法详解

    这篇文章主要介绍了C++之重载 重定义与重写用法详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    青山的青6062022-01-04
  • C/C++C语言中炫酷的文件操作实例详解

    C语言中炫酷的文件操作实例详解

    内存中的数据都是暂时的,当程序结束时,它们都将丢失,为了永久性的保存大量的数据,C语言提供了对文件的操作,这篇文章主要给大家介绍了关于C语言中文件...

    针眼_6702022-01-24
  • C/C++c++ 单线程实现同时监听多个端口

    c++ 单线程实现同时监听多个端口

    这篇文章主要介绍了c++ 单线程实现同时监听多个端口的方法,帮助大家更好的理解和学习使用c++,感兴趣的朋友可以了解下...

    源之缘11542021-10-27
  • C/C++C/C++经典实例之模拟计算器示例代码

    C/C++经典实例之模拟计算器示例代码

    最近在看到的一个需求,本以为比较简单,但花了不少时间,所以下面这篇文章主要给大家介绍了关于C/C++经典实例之模拟计算器的相关资料,文中通过示...

    jia150610152021-06-07
857