在 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. C++ 多态与虚拟:Class 语法语义

    1.object与class:在object-oriented programming编程领域,对象(object)有更严格的定义.对象是由数据结构和用于处理该结构的过程(称为methods)组成的实 ...

  2. [Contract] truffle-flattener 合并 Solidity 文件的依赖到一个文件

    使用 $ npm install truffle-flattener -g $ truffle-flattener <solidity-files> > output.sol 为什么 ...

  3. CSS属性继承问题,那些会被继承,哪些不继承?

    总的来能被继承的就是三大类 一,字体有关的的,font-开头的 二,文本有关的,text- 开头的 三,visibility , cursor 其它的基本都是不能被继承 比如说这个,你以为它继承了ma ...

  4. Util 应用框架 UI 全新升级

    Util UI 已经开发多年, 并在多家公司的项目使用. 不过一直以来, Util UI 存在一些缺陷, 始终未能解决. 最近几个月, Util 团队下定决心, 终于彻底解决了所有已知缺陷. Util ...

  5. 【技术流吃瓜】python可视化大屏舆情分析“张天爱“事件微博评论

    目录 一.事件背景 二.微热点分析 二.自开发Python舆情分析 2.1 Python爬虫 2.2 可视化大屏 2.2.1 大标题 2.2.2 词云图 2.2.3 条形图 2.2.4 饼图(玫瑰图) ...

  6. Linux部署Apache 网站服务器(httpd服务)

    一.项目导入: 某学院组建了校园网,建设了学院网站.现需要架设Web服务器来为学院网站安家,同时在网站上传和更新时,需要用到文件上传和下载,因此还要架设FTP服务器,为学院内部和互联网用户提供WWW. ...

  7. cesium教程9-加载倾斜摄影并解决高度问题

    无人机航拍的倾斜摄影,用照片和视频处理生成三维模型,一般照片都带有坐标信息,所以一般都能定位的比较准确,但是经常会出现高度偏差,这个时候就需要特殊处理了. 今天航拍建模的效果如下: 这个建模没有裁剪, ...

  8. Table 实现固定行和固定列

    需要用到的2个属性 table-layout : fixed position : sticky table-layout table-layout属性有两种特定值: auto(预设值)-表格的总宽度 ...

  9. ༺$Musique Collection 1$༻

    ~~头图~~ 自取捏 <\(Landslide\)>-\(Oh\,Wonder\) I know it hurts sometimes but You'll get over it You ...

  10. PageOffice 6 版本最简单的打开保存文件

    在OA办公.文档流转等各个Web系统中,实现最简单的打开编辑保存文件功能,调用PageOffice只需要几行代码就可以完成. 后端代码 在后端编写代码调用webOpen方法打开文件之前给SaveFil ...