C++ default 和delete的新用法

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

一、 类中的默认函数a.类中默认的成员函数1.默认构造函数2.默认析构函数3.拷贝构造函数4.拷贝赋值函数5.移动构造函数6.移动拷贝函数

b.类中自定义的操作符函数1.operator2.operator&3.operator&&4.operator*5.operator->6.operator->*7.operator new8.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成员,它没有类内初始化器且其类型未显示定义默认构造函数,则该类的默认构造函数被定义为删除的
时间: 2024-11-05 12:13:21

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

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

时间:2014.05.08 地点:基地 -------------------------------------------------------------------------------- 一.类中的默认函数 a.类中默认的成员函数 1.默认构造函数 2.默认析构函数 3.拷贝构造函数 4.拷贝赋值函数 5.移动构造函数 6.移动拷贝函数 b.类中自定义的操作符函数 1.operator 2.operator& 3.operator&& 4.operator* 5.op

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

原文https://www.cnblogs.com/lsgxeva/category/1107731.html #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #include <vector> #include <map> //c++11 类默认函数的控制:"=default" 和 "=delete"函数 /* C++ 的类有

Java 8 的日期时间新用法

1.// The current date and timeLocalDateTime.now();// construct from valuesLocalDate.of(2012, 12, 12);LocalDate.of(2012, Month.DECEMBER, 12);// Somewhere in the middle of 1970LocalDate.ofEpochDay(150);// the train I took home todayLocalTime.of(17, 18)

CSS选择器的新用法

前面的话 现在,预处理器(如sass)似乎已经成为开发CSS的标配,正如几年前jQuery是开发JS的标配一样.JS的querySelector借鉴了jQuery的选择器思想,CSS选择器也借鉴了预处理器的变量定义.选择器嵌套.代码块重用等常用功能.本文将详细介绍CSS选择器的新用法 变量 一般地,我们在进行web开发时,会有一套变量定义规范,以sass为例,如下所示 // 颜色定义规范 $color-background : #222 $color-background-d : rgba(0,

C++11之for循环的新用法《转》

相关资料:https://legacy.gitbook.com/book/changkun/cpp1x-tutorial/details C++11之for循环的新用法 C++使用如下方法遍历一个容器: #include "stdafx.h" #include<iostream> #include<vector> int main() { std::vector<int> arr; arr.push_back(1); arr.push_back(2)

Excel表格中Ctrl组合快捷键的新用法,你知道多少?

在日常生活和工作中,学会使用一些快捷键是很有必要的一个事情.那么大家知不知道同样的快捷键在不同的情况下是有不同的功能的.接下来给大家看一些表格中Ctrl组合快捷键的新用法.No.1:[Ctrl+A]跳出函数参数帮助窗口我们都知道Ctrl+A是全选的功能,其实当我们在任意单元格中输入函数,然后点击[Ctrl+A],接着就可以跳出函数参数帮助的窗口了.No.2[Ctrl+E]字串符重组当我们在表格中输入一些数据之后,如在重组下输入一个"张组长",点击该处下方的单元格,使用[Ctrl+E]快

SQL Server DML(UPDATE、INSERT、DELETE)常见用法(一)

1.引言 T-SQL(Transact Structured Query Language)是标准的SQL的扩展,是程序和SQL Server沟通的主要语言. T-SQL语言主要由以下几部分组成: 数据定义语言(DDL):用来建立数据库.数据库对象等,如CREATE TABLE.DROP TABLE等. 数据控制语言(DCL):控制数据库的存取许可.权限等,如GRANT等. 数据操纵语言(DML):用于插入.修改.删除和查询数据库中数据,如SELECT.INSERT.UPDATE.DELETE等

C++11的default和delete关键字

C11的新特性实在是太多了,这2个关键字关注的人倒是少了很多,其中有一个原因便是编译器支持得太慢了(VS到VS2013才支持上),不过这2个关键字那真是极为有用的,下面我们来看看. [default关键字] 首先我们有一个字符串类: class CString { char* _str; public: //构造函数 CString(const char* pstr) : _str(nullptr) { UpdateString(pstr); } //析构函数 ~CString() { if (

第四篇:new和delete的基本用法

前言 new和delete是C++中用来动态管理内存分配的运算符,其用法较为灵活.如果你对它们的几种不同用法感到困惑,混淆,那么接着看下去吧. 功能一:动态管理单变量/对象空间 下面例子使用new为单个变量/对象开辟空间: 1 // 创建一个指向整型元素的指针pi,其所指对象为整数100. 2 int *pi = new int(100); 3 4 // 创建一个指向字符串元素的指针ps,其所指对象为字符串"ssssssssss". 5 string *ps = new string(