在 C++ 11 中,"= default""= delete" 函数使我们能够显示指定成员函数是否自动生成。

其中,"= delete" 使我们能够避免所有函数 (特殊成员函数,普通成员函数和非成员函数) 参数中出现错误的类型提升 (导致非预期的函数调用)。

C++ 特殊成员函数:

即使用户不自定义,编译器也会自动生成的成员函数,包括

  • 构造函数
  • 拷贝构造函数
  • 拷贝赋值运算符
  • 移动构造函数
  • 移动赋值运算符
  • 析构函数

"= default" 函数

= default 可以用于任何特殊成员函数,比如显示指定特殊成员函数使用默认的函数实现,定义非公有的特殊成员函数,或者在某些情况下恢复特殊成员函数的自动生成。

示例:

struct widget
{
widget() = default; inline widget& operator=(const widget&);
}; inline widget& widget::operator=(const widget&) = default;

你可以在类的外部指定特殊成员函数为 = default,只要它是内联的。

由于默认特殊成员函数的性能优势,当需要默认行为时建议使用自动生成的特殊成员函数而不是使用空函数体。为此可以显示指定特殊成员函数为 = default 或者不声明它。

"= delete" 函数

定义函数(任何函数)为 = delete 防止其被定义和调用。

防止编译器生成你不需要的特殊成员函数。

= default不同,"= delete" 函数必须在函数声明的时候指定其为 = default, 而不能在之后重新声明其为 = default

示例:

struct widget
{
// deleted operator new prevents widget from being dynamically allocated.
void* operator new(std::size_t) = delete;
};

防止成员和非成员函数参数发生错误的类型提升导致非预期的函数调用。

示例:

// deleted overload prevents call through type promotion of float to double from succeeding.
void call_with_true_double_only(float) = delete;
void call_with_true_double_only(double param) { return; }

上面这个例子中,通过传递 float 类型参数来调用 call_with_true_double_only 会产生一个编译错误, 但是使用 int 类型参数则不会,int 类型的参数会被转换提升为 double 类型, 尽管这不是想要的结果。

为保证任何非 double 参数的调用能够产生编译错误,可以声明一个模板函数并指定其为 = delete

示例:

template < typename T >
void call_with_true_double_only(T) = delete; //prevent call through type promotion of any T to double from succeeding. void call_with_true_double_only(double param) { return; } // also define for const double, double&, etc. as needed.

"= default""= delete" 函数的优势

在 C++ 中,如果用户不自定义,编译器可以自动生成特殊成员函数。这对简单类型是方便的,但是复杂类型经常会自定义特殊成员函数,使用 = delete 可以防止这些特殊成员函数被自动创建。

在实践中:

  • 如果任何构造函数已经显示声明,那么默认构造函数就不会自动生成。
  • 如果虚析构函数已经显示声明,那么默认西沟函数就不会自动生成。
  • 如果移动构造函数或者移动赋值操作符已经显示声明,那么:
    • 拷贝构造函数就不会自动生成
    • 拷贝赋值运算符就不会自动生成
  • 如果拷贝构造函数,拷贝赋值操作符,移动构造函数或者移动赋值操作符已经显示声明,那么:
    • 移动构造函数就不会自动生成
    • 移动赋值运算符就不会自动生成

注意:

C++11 标准还规定了如下规则:

  • 如果拷贝构造函数或者析构函数被显示声明,那么拷贝赋值运算符就不会自动生成
  • 如果拷贝赋值运算符或者析构函数被显示声明,那么拷贝构造函数就不会自动生成

这两种情况下, Visual Studio 仍然会自动生成必要的函数,并不会产生告警。

在 C++11 之前,非拷贝类型的通用实现:

struct noncopyable
{
noncopyable() {}; private:
noncopyable(const noncopyable&);
noncopyable& operator=(const noncopyable&);
};

上述代码存在一些问题:

  • 拷贝构造函数声明为私有导致了默认构造函数无法自动生成,必须显示声明默认构造函数,即使他什么也不做。
  • 即使显示声明的默认构造函数声明也不做,编译器也将其认为是复杂的,其不如自动生产的默认构造函数来的高效,并且 noncopyable 也不会认为是 POD 类型。
  • 即使拷贝构造函数和拷贝赋值运算符被声明为私有的,成员函数和友元仍然能够调用他们,如果他们声明了但未定义,调用会产生链接错误。
  • 尽管这是通用的实现方式,但是其意图并不明显,除非你了解所有特殊成员函数自动生成的规则。

在 C++11 中, 非拷贝类型可以以更直接的方式实现从而解决了上述问题:

struct noncopyable
{
noncopyable() = default;
noncopyable(const noncopyable&) = delete;
noncopyable& operator=(const noncopyable&) = delete;
};

关于 "= default" 和 "= delete" 函数的更多相关文章

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

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

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

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

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

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

  4. C++ default 和delete的新用法

    C++中的默认函数与default和delete用法一. 类中的默认函数a.类中默认的成员函数1.默认构造函数2.默认析构函数3.拷贝构造函数4.拷贝赋值函数5.移动构造函数6.移动拷贝函数 b.类中 ...

  5. 重载operator new delete函数

    可以重载global的operator new delete 函数,细节如下: MyNewDelete.h #pragma once #include <stdlib.h> #includ ...

  6. default和delete

    在C++中,有四类特殊的成员函数,分别为:默认构造函数,默认析构函数,默认拷贝构造函数,默认赋值运算符.他们的作用为创建.初始化.销毁.拷贝对象. 虽然在类A中什么都没有定义,但是编译会通得过,因为编 ...

  7. C++中 destory() 和deallocate()以及delete函数的相关性和区别性

    这里非常的绕口  需要仔细的来看看: destory(): 显示调用一个对象的析构函数 相当于释放一个对象需要释放的一些动态内存 为下次真正释放对象做准备 deallocate():真正的释放一个内存 ...

  8. STL--C++中 destory() 和deallocate()以及delete函数的相关性和区别性,destorydeallocate

    这里非常的绕口  需要仔细的来看看: destory(): 显示调用一个对象的析构函数 相当于释放一个对象需要释放的一些动态内存 为下次真正释放对象做准备 deallocate():真正的释放一个内存 ...

  9. C++中 =default 和 =delete 使用

    编译器默认为一个类生成的默认函数 默认构造函数 默认析构函数 默认拷贝构造函数 默认赋值函数 移动构造函数 移动拷贝函数 class DataOnly { public: DataOnly () // ...

  10. C++11的override、default和delete关键字

    最近在参与组里的项目时接触了很多以前自己没太了解的C++语法(尤其是C++11以后出现的),今天给大家讲一下C++11新出的override和default关键字. override关键字主要在声明类 ...

随机推荐

  1. 不改一行代码,轻松拥有企业级微服务治理|MSE微服务治理专业版重磅发布

    ​简介:随着业务的发展,微服务拆分越来越复杂,微服务的治理也成了一个比较令人头疼的问题.有没有更加简单且高效的方法来解决微服务治理的难题? 作者:十眠 随着业务的发展,微服务拆分越来越复杂,微服务的治 ...

  2. [FAQ] 适用于 macOS / Arm64 (M1/M2) 的 VisualBox

      使用与 Windows.Linux.macOS 的x86架构的一般在下面地址中下载: Download VisualBox:https://www.virtualbox.org/wiki/Down ...

  3. [FAQ] Vmmem 内存占用高的问题 -Win10 -WLS2

    1按下Windows + R 键,输入 %UserProfile% 并运行进入用户文件夹 2新建文件 .wslconfig ,然后记事本编辑 3 填入以下内容并保存, memory为系统内存上限,这里 ...

  4. fastreport .net打印普通报表

    fastreport .net打印普通报表 前言: .net代码层先不记录在这,后续会单独写一篇博客来记录. 直接在工具上进行功能点的实现 一.效果图 二.功能点 分页 分页小计 金额大写 三.功能点 ...

  5. SAP集成技术(一)历史

    最近想读一本书<SAP Interface Management Guide>,打算边读边记录一些笔记.翻译主要由ChatGPT完成. 本文链接:https://www.cnblogs.c ...

  6. Centos 密码过期问题 password has expired

    1.这个主要是由/etc/login.defs参数文件中的一些参数控制的的.它主要用于用户账号限制PASS_MAX_DAYS 60     #密码最大有效期,此处参数PASS_MAX_DAYS为60, ...

  7. istio sidecar 工作方式

    istio 是什么 Istio 是一个开放源代码的服务网格,它为基于微服务的应用程序提供了一种统一的方式来连接.保护.监控和管理服务.Istio 主要解决的是在微服务架构中的服务间通信的复杂性问题,它 ...

  8. Nokia 5GC 产品概览

    目录 文章目录 目录 Nokia SR OS Nokia NSP NFM-P Nokia 7750 SR-MG 5G User Plane Forwarding Mobile Gateway Non- ...

  9. 国产linux系统(银河麒麟,统信uos)使用 PageOffice 国产版在线动态填充 word 文件

    PageOffice 国产版 :支持信创系统,支持银河麒麟V10和统信UOS,支持X86(intel.兆芯.海光等).ARM(飞腾.鲲鹏.麒麟等)芯片架构. 在实际的Word文档开发中,经常需要自动填 ...

  10. VSCode:Mac(M1)配置VSCode中C/C++环境(只需三步)

    只需三步. 1. 下载CodeLLDB插件: 2. 配置tasks.json { "version": "2.0.0", "tasks": ...