C++中 ‘=default ’及‘ =delete ’的使用

目录
  • 1 =default
    • 2 =delete

前言:

C++的类有四类特殊成员函数,它们分别是:默认构造函数、析构函数、拷贝构造函数、拷贝赋值运算符。如果实际编码时没有显示定义,那么编译器将会默认生成这四类成员函数。使用=default=delete可以控制编译器默认函数体的使用。

1 =default

C++11新增了=default标识,编译器看到后,会生成默认的执行效率更高的函数定义体,同时会减轻编码时的工作量。当然,这里会引入一个问题,既然编译器会默认生成构造函数,那么=default的优势在哪里呢?回答这个问题之前,先看下这段代码

class Test{
public:
    Test(int a):x(a){};
private:
    int x;
};
int main ()
{
  Test test;
  return 0;
}

众所周知,上面这段是编译不过的,原因是因为在Test类中我们自己定义了一个构造函数,编译器看到后就不会再生成默认构造函数给我们,如果要解决这个编译问题的话需要我们提供一个没有参数的构造函数。

如:

 Test(){};

在类中加了上面的代码之后,编译器就会编译通过,但是在试想一下,如果这个类很大,且需要我们在类中初始化的成员很多呢?这个时候我们需要提供的这个默认构造函数就变得的很庞大,浪费我们很多时间进行变量的初始化,写一堆没有技术的赋值或者其它初始化语句。同样,拷贝构造函数和拷贝赋值函数也是一样。

=default就给我们提供了这样一个功能,加上之后,编译器就会给我们默认生成函数体,减轻工作量。

上面的类就这可以这些写:

class Test{
public:
    Test(int a):x(a){};
    Test()=default;
private:
    int x;
};

当然,=default不但可以在类成员内部添加也可以在类之外添加,但是使用=default时,必须遵守一个准则:default 函数特性只能用于类的特殊成员函数或者函数没有默认参数。 =default

写在类之外的方式如下:

class Test{
public:
    Test(int a):x(a){};
    Test()=default;
    Test(const Test& ts);
    Test& operator = (const Test& ts);
private:
    int x;
};
Test::Test(const Test& ts) =default;
Test& Test::operator = (const Test& ts) =default;

上面的代码中演示了=default在类成员外部使用的场景。但是类中确没有析构函数,编码时,如果涉及到类的继承和派生,尤其是通过基类指针指向了派生类对象,当调用delete删除派生对象时,如果基类没有显示定义析构函数,编译器会为基类默认生成析构函数,基类对象会被正常释放,但是也会产生一个问题,派生类没有正确释放,可能会产生内存泄露等问题。正确解决这种问题的做法是在基类中显示定义一个虚析构函数。这种方法在C++11之前是我们解决这种问题经常使用的,但是C++11之后,可以使用=default ,从而减轻我们的编码量,且编译器生成的代码效率更高。

代码如下所示:

class Base{
public:
    virtual ~Base()=default;
private:
    int x;
};
class A : public Base{
private:
    int y;
};
int main ()
{
  Base *pBase = new A;
  delete pBase;
  return 0;
}

2 =delete

C++11之前,delete是和new配对使用的,释放程序在堆上开辟得空间,将资源返还给操作系统,C++11之后,delete又多了一个含义既:禁用成员函数的使用。使用方法为:在函数名称后面加上=delete。

下面代码定义了一个类,类里面定义了一个整型的成员变量,在main函数中使用时,创建了两个类的实例,一个传入参数用整型一个用浮点型,

代码如下:

class Test {
public:
    Test()=delete;
    Test(int a):x(a) {std::cout<<x<<std::endl;}
private:
    int x;
};
int main() {
    Test test1(1);
    Test test2(1.1);
    return 0;
}

如上,这段代码是可以编译通过的,因为这段代码在编译时发生了隐式转换,将浮点型数据转成了整型,代价是损失了精度。代码运行后输出的结果都是:1。

如果不想在传入非整型的数据时编译通过,就可以使用=delete来抑制这种问题的产生。如使用=delete解决上面的问题,

代码如下:

class Test {
public:
    Test(int a):x(a) {std::cout<<x<<std::endl;}
    Test(double)=delete;
private:
    int x;
};
int main() {
    Test test1(1);
    Test test2(1.1);
    return 0;

编译时报错信息为:

main.cpp:23:19: error: use of deleted function ‘Test::Test(double)'
   23 |     Test test2(1.1);
      |                   ^
main.cpp:17:5: note: declared here
   17 |     Test(double)=delete;
      |     ^~~~

如上可知,使用=delete后,可以使我们禁用一些不需要编译器生成的默认函数,还可以避免因为数据类型原因导致的错误的函数调用。

到此这篇关于C++中 =default 及 =delete 使用的文章就介绍到这了,更多相关C++中 =default 和 =delete 使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

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

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

  • C++中 ‘=default ’及‘ =delete ’的使用

    目录 1 =default 2 =delete 前言: C++的类有四类特殊成员函数,它们分别是:默认构造函数.析构函数.拷贝构造函数.拷贝赋值运算符.如果实际编码时没有显示定义,那么编译器将会默认生成这四类成员函数.使用=default和=delete可以控制编译器默认函数体的使用. 1 =default C++11新增了=default标识,编译器看到后,会生成默认的执行效率更高的函数定义体,同时会减轻编码时的工作量.当然,这里会引入一个问题,既然编译器会默认生成构造函数,那么=defaul

  • C++中 ‘=default ’及‘ =delete ’的使用

    目录 1 =default 2 =delete 前言: C++的类有四类特殊成员函数,它们分别是:默认构造函数.析构函数.拷贝构造函数.拷贝赋值运算符.如果实际编码时没有显示定义,那么编译器将会默认生成这四类成员函数.使用=default和=delete可以控制编译器默认函数体的使用. 1 =default C++11新增了=default标识,编译器看到后,会生成默认的执行效率更高的函数定义体,同时会减轻编码时的工作量.当然,这里会引入一个问题,既然编译器会默认生成构造函数,那么=defaul

  • C++中new和delete的使用方法详解

    C++中new和delete的使用方法详解 new和delete运算符用于动态分配和撤销内存的运算符 new用法:           1.     开辟单变量地址空间 1)new int;  //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给整型指针a. 2)int *a = new int(5) 作用同上,但是同时将整数赋值为5           2.     开辟数组空间 一维: int *a = new in

  • 实例理解SQL中truncate和delete的区别

    本文以一个简单实例为大家介绍了SQL中truncate和delete的区别,帮助大家理解,具体内容如下 ---创建表Table1 IF OBJECT_ID('Table1','U') IS NOT NULL DROP TABLE Table1 GO CREATE TABLE Table1 (ID INT NOT NULL, FOID INT NOT NULL) GO --插入测试数据 INSERT INTO Table1 VALUES(1,101),(2,102),(3,103),(4,104)

  • js删除数组中的元素delete和splice的区别详解

    例如有一个数组是 :var textArr = ['a','b','c','d']; 这时我想删除这个数组中的b元素: 方法一:delete 删除数组 delete textArr[1]  结果为: ["a",undefined,"c","d"] 只是被删除的元素变成了 undefined 其他的元素的键值还是不变. 方法二:aplice 删除数组 splice(index,len,[item]) 注释:该方法会改变原始数组. index:数组开

  • C++中的new/delete、构造/析构函数、dynamic_cast分析

    1,new 关键字和 malloc 函数区别(自己.功能.应用): 1,new 关键字是 C++ 的一部分: 1,如果是 C++ 编译器,则肯定可以用 new 申请堆空间内存: 2,malloc 是由 C 库提供的函数: 1,如果没有相应的库,malloc 将不能使用: 2,有些特殊的嵌入式开发中,少了 C 库,则就不能动态内存分配: 3,new 以具体类型为单位进行内存分配: 1,面向对象中一般用 new,不用 malloc: 4,malloc 以字节为单位进行内存分配: 5,new 在申请内

  • 详解MySQL中default的使用

    NULL 和 NOT NULL 修饰符.DEFAULT 修饰符,AUTO_INCREMENT 修饰符. NULL 和 NOT NULL 修饰符 可以在每个字段后面都加上这 NULL 或 NOT NULL 修饰符来指定该字段是否可以为空(NULL), 还是说必须填上数据 (NOT NULL).MySQL 默认情况下指定字段为 NULL 修饰符,如果一个字段指定为NOT NULL, MySQL 则不允许向该字段插入空值(这里面说的空值都为 NULL),因为这是 "规定". /* 创建好友表

  • 深入理解C++中的new/delete和malloc/free动态内存管理及区别介绍

    malloc/free和new/delete的区别 malloc/free是C/C++标准库的函数:new/delete是C++操作符. malloc/free只是动态分配内存空间/释放空间:new/delete除了分配空间还会调用构造函数和析构函数进行初始化与清理资源. malloc/free需要手动计算类型大小且返回值类型为void*:new/delete可自动计算类型的大小,返回对应类型的指针. malloc/free管理内存失败会返回0:new/delete等的方式管理内存失败会抛出异常

  • python中使用np.delete()的实例方法

    在python列表中,如果我们想要删除一个或者连续几个元素,可以使用del()方法,在numpy数组,如果想要删除元素,可以使用numpy.delete()方法,但是numpy数组不支持删除数组元素,numpy.delete() 返回删除了某些元素的新数组. 1.np.delete()方法 numpy.delete()适用于numpy ndarray数组. 但是numpy数组不支持删除数组元素,numpy.delete() 返回删除了某些元素的新数组. 2.使用语法 numpy.delete(a

  • 你知道C++中new和delete为什么要匹配使用吗

    目录 前言 new 和 delete 做了什么 内置类型 new 和 new [] delete 和 delete [ ] 自定义类型 new 和 new [] delete 和 delete [ ] 问题 自定义类型为什么要匹配使用 内置类型不匹配为什么不报错 疑惑 前言 关于 new 和 delete 的使用相信大家并不陌生,可是为什么使用 new 的时候要用 delete,使用 new[] 的时候又要用 delete[].使用 delete 释放 new[] 申请的内存又会发生什么?为什么

随机推荐