C++中的默认函数与default和delete用法

一、 类中的默认函数
a.类中默认的成员函数
1.默认构造函数
2.默认析构函数
3.拷贝构造函数
4.拷贝赋值函数
5.移动构造函数
6.移动拷贝函数 b.类中自定义的操作符函数
1.operator
2.operator&
3.operator&&
4.operator*
5.operator->
6.operator->*
7.operator new
8.operator delete 同时C++规定,一旦程序员实现了这些函数的自定义版本,则编译器不会再自动生产默认版本。注意只是不自动生成默认版本,当然还是可手动生成默认版本的。当我们自己定义了待参数的构造函数时,我们最好是声明不带参数的版本以完成无参的变量初始化,此时编译是不会再自动提供默认的无参版本了。我们可以通过使用关键字default来控制默认构造函数的生成,显式地指示编译器生成该函数的默认版本。比如:
class MyClass
{
public:
MyClass()=default; //同时提供默认版本和带参版本,类型是POD的
MyClass(int i):data(i){}
private:
int data;
}; 有些时候我们希望限制默认函数的生成。典型的是禁止使用拷贝构造函数,以往的做法是将拷贝构造函数声明为private的并不提供实现,这样当拷贝构造对象时编译不能通过,C++11则使用delete关键字显式指示编译器不生成函数的默认版本。比如:
class MyClass
{
public:
MyClass()=default;
MyClass(const MyClass& )=delete;
......
} 当然,一旦函数被delete过了,那么重载该函数也是非法的,该函数我们习惯上称为删除函数。 二、default和delete的其他用途
上面我们已经看到在类中我们可用default和delete修饰成员函数,使之成为缺省函数或者删除函数,在类的外面,default可以在类定义之外修饰成员函数,比如:
class MyClass
{
public:
MyClass()=default;
MyClass() &operator=(const MyClass& );
);
//在类的定义外用default来指明缺省函数版本
inline MyClass& MyClass::operator=(const MyClass& )=default;
还可以MyClass& MyClass::operator=(const MyClass& )=default;但是这种类外定义合成的成员就不是内联函数。
与=default 不同,=delete必须出现在函数的第一次声明中。因为一个默认的成员只影响为这个成员生成的代码,因此=default 直到编译生成代码时才需要,而编译器必须早早知道一个函数是否是删除的,以便禁止试图使用它的操作。 一般情况下,析构函数不能定义为删除的,因为如果析构函数被删除,就无法删除此类型的对象了。对于一个删除了析构函数的类型,编译器将不允许定义该类型的变量或创建该类型的临时对象,而且如果一个类有某个成员的类型删除了析构函数,也不能定义该类的变量或临时对象,因为一个成员的析构函数是删除的,则该成员无法销毁,包含它的类也就没法销毁。虽然对于删除了析构函数的类型,我们不能定义这种类型的变量或成员但可以动态分配这种类型的对象,比如:
Struct NoDtor{
NoDtor()=default;
~NoDtor()=default;
};
NoDtor *P=new NoDtor();//正确,但是我能delete P
但是有时析构函数也是可以delete的,这样做的目的是我们在指定内存位置进行内存分配时并不需要析构函数来完成对象级别的清理,这时我们可显示删除析构函数来限制自定义类型在栈上或者静态的构造。 关于delete的显式删除,并非局限于成员函数,比如:
void Func(int i){};
void Func(char c)=delete; //显式删除char版本
int main()
{
Func(3);
Func('c’); //无法编译通过
return 0;
}
这里因为Func的char版本已经被删除,故Func('c')会编译失败。由此我们也知default是只局限作用于类的部分成员函数的。于是我们还可用delete来避免不必要的隐式数据类型转换。比如:
class MyClass
{
public:
MyClass(int i){};
MyClsss(char c)=delete; //删除char版本的构造函数
};
void Fun(MyClass m){}
int main()
{
Func(3);
Func('a'); //编译不能通过
MyClass m1(3);
MyClass m2('a'); //编译不能通过
}
这是因为char版本的构造函数被删除后,试图从char构造MyClass对象的方式是不允许的了。但去掉这句的函数删除后,编译器会隐式的将a转换为整型使得编译通过,调用的是整型构造函数,这可能并不是你所想要的。 但是如果这样:
class MyClass
{
public:
MyClass(int i){};
explicit MyClsss(char c)=delete; //删除explicit的char版本的构造函数
};
void Fun(MyClass m){}
int main()
{
Func(3);
Func('a'); //编译可通过
MyClass m1(3);
MyClass m2('a'); //编译不能通过
} 将构造函数explicit后,构造函数一样的还是不能发生char的构造,因为char构造版本被删除了,但在Func的调用中,编译器会尝试将c转换为int,即Func(\\a')会调用一次MyClass(int )构造,顺利通过编译。于是我们不提倡explicit和delete混用。对与普通函数delete也有类型的效果。 delete的用法还包括删除operator new操作符,编码在堆上分配该类的对象
如:void* operator new(std::size_t)=delete; 合成的拷贝控制成员可能是删除的,如果一个类有数据成员不能默认构造、拷贝、复制或销毁,则对应的成员函数将被定义为删除的。因此:
如果类的某个成员的析构函数是删除的或不可访问的,那么类的合成析构函数被定义为删除的。
如果类的某个成员的拷贝构造函数是删除的或不可访问的,则类的合成拷贝构造函数也被定义为删除的。
如果类的某个成员的拷贝赋值运算符是删除的或不可访问的,或是类有一个const的或引用成员,则类的合成拷贝赋值运算符被定义为删除的。
如果类的某个成员的析构函数是删除的或不可访问的,或是类有一个引用成员,它没有类内初始化器,或是类有一个const成员,它没有类内初始化器且其类型未显示定义默认构造函数,则该类的默认构造函数被定义为删除的

C++ default 和delete的新用法的更多相关文章

  1. C# 7.1中default关键字的新用法

    default 关键字有两类用法 switch语句中指定默认标签 默认值表达式 switch 语句 int caseSwitch = 1; switch (caseSwitch) { case 1: ...

  2. c++11 类默认函数的控制:"=default" 和 "=delete"函数

    c++11 类默认函数的控制:"=default" 和 "=delete"函数 #define _CRT_SECURE_NO_WARNINGS #include ...

  3. c++11 类默认函数的控制:"=default" 和 "=delete"函数 void fun() = default; void fun()=delete;

    转自:lsgxeva #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #includ ...

  4. c++基础知识_c++11 类默认函数的控制:"=default" 和 "=delete"函数

    #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #include <vecto ...

  5. 精读《Epitath 源码 - renderProps 新用法》

    1 引言 很高兴这一期的话题是由 epitath 的作者 grsabreu 提供的. 前端发展了 20 多年,随着发展中国家越来越多的互联网从业者涌入,现在前端知识玲琅满足,概念.库也越来越多.虽然内 ...

  6. 详解Vue的slot新用法

    摘要: 理解Vue插槽. 作者:前端小智 原文:vue 2.6 中 slot 的新用法 Fundebug经授权转载,版权归原作者所有. 为了保证的可读性,本文采用意译而非直译. 最近发布不久的Vue ...

  7. vue 3 学习笔记 (六)——watch 、watchEffect 新用法

    选项式API与之前写法相同,本篇文章主要通过 Options API 和 Composition API 对比 watch 的使用方法,让您快速掌握 vue3 中 watch 新用法.建议收藏! 一. ...

  8. vue 3 学习笔记 (七)——vue3 中 computed 新用法

    vue3 中 的 computed 的使用,由于 vue3 兼容 vue2 的选项式API,所以可以直接使用 vue2的写法,这篇文章主要介绍 vue3 中 computed 的新用法,对比 vue2 ...

  9. C++虚函数的新用法

    1.今天在segmentfault上看到了一个C++虚函数的新用法,先上代码 #include <iostream> using namespace std; class B { publ ...

随机推荐

  1. css 选择器样式优先级

    !important > 行内 >id > class >tag >*

  2. WebApi服务Uri加密及验证的两种方式

    最近的一个项目要求服务端与UI层分离,业务层以WebApi方式向外提供所有业务服务,服务在数据保密性方面提出了要求,主要包括: 1:客户端认证: 2:服务请求超时(默认5分钟): 3:服务Get请求的 ...

  3. Xcode找不到模拟器出现"My Mac"

    问题如图: 步骤一. 找到target->built settings->Architectures->Base SDK, 选择你需要的版本;如果还是不行,看步骤二. 步骤二. 1) ...

  4. 自动完成--autoComplete插件(2)

    远端的也可以成为本地的数据 4) lookupLimit 类型:数字 说明:本地数据显示的最大条数,服务器段的没有效果,服务器端的可以后台设置 默认:没有限制 5) lookupFilter 类型: ...

  5. spring-HelloWorld

    准备工作,安装SpringIDE,找到SpringSource-tool-suit,然后按照, 关键的一部在与找到之后该安转那些呢,答案是只安转带有SpringIDE的, 有四个,且不要点击联网进行更 ...

  6. [Noi2016十连测第三场]线段树

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...

  7. bootstrap 双层模态框的实现

    <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...

  8. shell命令bc

    简介 bc支持浮点数的精度运算(Bash不支持浮点数运算) 运行方式 一.CLI 二.PIPE 示例 一.浮点数运算 变量scale:设置小数点后面的位数  # 默认scale=0 echo &quo ...

  9. 如何判断ios设备中是否安装了某款应用

    URL Schemes关键字研究一下即可 常见得URL Schemes见http://www.cnblogs.com/huangzs/p/4491286.html if ([[UIApplicatio ...

  10. Java反射API使用实例

    /**     * 访问Class对应的类所包含的注释:getAnnotation();getDelaredAnnotation();     * 访问Class对应的类所包含的内部类:getDecl ...