IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++11 noexcept -> 正文阅读

[C++知识库]C++11 noexcept

1、noexcept修饰符

  1. C++98中使用throw()进行动态异常声明
    void except_func() throw(int ,double){ … }
    在except_func函数后定义了一个动态异常声明throw(int, double)。 该声明指出了except_func可能抛出的异常类型.但是此特性很少被使用,故被弃用

  2. C++11使用noexcept取代throw()进行动态异常声明
    语法上有两种形式
    void except_func() noexcept {…}
    void except_func() noexcept(常量表达式) {…}
    常量表达式会被转化为bool类型的值,该值为true表示不会抛出异常,即相当于不带表达式的形式。

2、noexcept作用

noexcept作用之一就是阻止异常的传播和扩散。

#include <iostream>

void thowexcept(){ throw 1;}
void NoBlockThrow(){ thowexcept();}
void BlockThrow() noexcept { thowexcept();}
int main(){
    try{
        thowexcept();
    }
    catch(...){
        std::cout << "found throw" << std::endl;
    }
    
    try{
        NoBlockThrow(); //默认noexcept(false)
    }
    catch(...){
        std::cout << " NoBlockThrow "  << std::endl;
    }

    try{
        BlockThrow(); //在被noexcept声明的函数中发生异常,程序调用terminate结束程序
    }
    catch(...){
        std::cout << " BlockThrow "<< std::endl;
    }
    return 0;
}

在这里插入图片描述
虽然terminate()调用可能带来很多问题,比如无法保证析构函数正常调用,无法保证栈的自动释放等。但是很多时候暴力终止程序是最简单有效的办法。事实上,noexcept被广泛的,系统的用于c++11的标准库中,用于提高标准库的性能,以及满足一些阻止异常扩散的需求

3、noexcept操作符

noexcept作为操作符一般用于模板:
template < class T >
void noexecpt_func() noexcept( noexcept( T() ) ) {…}
noexecpt_func()是否为一个noexcept函数,取决于T()表达式是否会抛出异常。第二个exception就是一个noexcept操作符。

4、noexcept性能

因为在调用noexcept函数时不需要记录exception handler所以编译器可以生成更efficient的code(但实际编译器是否优化noexcept不一定,但理论上noexcept给了编译器更多优化的机会)。另外编译器在编译一个非noexcept的函数时有可能会生成很多冗余的代码,这些代码虽然只在出错的时候执行,但还是会对instruction cache造成影响,进而影响程序整体的performance。
下面是一段代码的noexcept(fasle)和noexcept的汇编代码比较

void foo();
struct Obj
{
    ~Obj();
};
void goo()
{
    Obj obj;
    foo();
}

4.1 noexcept(false)汇编代码

	.file	"testnoexcept.cpp"
	.text
	.section	.text.unlikely,"ax",@progbits
.LCOLDB0:
	.text
.LHOTB0:
	.p2align 4,,15
	.globl	_Z3goov
	.type	_Z3goov, @function
_Z3goov:
.LFB0:
	.cfi_startproc
	.cfi_personality 0x3,__gxx_personality_v0
	.cfi_lsda 0x3,.LLSDA0
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	subq	$16, %rsp
	.cfi_def_cfa_offset 32
.LEHB0:
	call	_Z3foov
.LEHE0:
	leaq	15(%rsp), %rdi
	call	_ZN3ObjD1Ev
	addq	$16, %rsp
	.cfi_remember_state
	.cfi_def_cfa_offset 16
	popq	%rbx
	.cfi_def_cfa_offset 8
	ret
.L3:
	.cfi_restore_state
	movq	%rax, %rbx
	jmp	.L2
	.globl	__gxx_personality_v0
	.section	.gcc_except_table,"a",@progbits
.LLSDA0:
	.byte	0xff
	.byte	0xff
	.byte	0x1
	.uleb128 .LLSDACSE0-.LLSDACSB0
.LLSDACSB0:
	.uleb128 .LEHB0-.LFB0
	.uleb128 .LEHE0-.LEHB0
	.uleb128 .L3-.LFB0
	.uleb128 0
.LLSDACSE0:
	.text
	.cfi_endproc
	.section	.text.unlikely
	.cfi_startproc
	.cfi_personality 0x3,__gxx_personality_v0
	.cfi_lsda 0x3,.LLSDAC0
	.type	_Z3goov.cold.0, @function
_Z3goov.cold.0:
.LFSB0:
.L2:
	.cfi_def_cfa_offset 32
	.cfi_offset 3, -16
	leaq	15(%rsp), %rdi
	call	_ZN3ObjD1Ev
	movq	%rbx, %rdi
.LEHB1:
	call	_Unwind_Resume
.LEHE1:
	.cfi_endproc
.LFE0:
	.section	.gcc_except_table
.LLSDAC0:
	.byte	0xff
	.byte	0xff
	.byte	0x1
	.uleb128 .LLSDACSEC0-.LLSDACSBC0
.LLSDACSBC0:
	.uleb128 .LEHB1-.LCOLDB0
	.uleb128 .LEHE1-.LEHB1
	.uleb128 0
	.uleb128 0
.LLSDACSEC0:
	.section	.text.unlikely
	.text
	.size	_Z3goov, .-_Z3goov
	.section	.text.unlikely
	.size	_Z3goov.cold.0, .-_Z3goov.cold.0
.LCOLDE0:
	.text
.LHOTE0:
	.ident	"GCC: (GNU) 8.4.1 20200928 (Red Hat 8.4.1-1)"
	.section	.note.GNU-stack,"",@progbits

4.2 noexcept汇编代码

	.file	"testnoexcept.cpp"
	.text
	.p2align 4,,15
	.globl	_Z3goov
	.type	_Z3goov, @function
_Z3goov:
.LFB0:
	.cfi_startproc
	subq	$24, %rsp
	.cfi_def_cfa_offset 32
	call	_Z3foov
	leaq	15(%rsp), %rdi
	call	_ZN3ObjD1Ev
	addq	$24, %rsp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE0:
	.size	_Z3goov, .-_Z3goov
	.ident	"GCC: (GNU) 8.4.1 20200928 (Red Hat 8.4.1-1)"
	.section	.note.GNU-stack,"",@progbits

5、noexcept安全性

《深入理解c++11》中是这么说的。我这里暂时还不知道怎么理解 请有知道的小伙伴帮忙留言
在这里插入图片描述

6、什么时候使用

  1. 现在编译器在好路径上异常没有影响,noexcept可能的作用是减小体积
  2. 推荐在构造、复制等常用操作标记noexcept,这样性能提升可能会比较大。例如vector不会使用你的类move操作,除非它被标记为noexcept(有的编译器能自动推导)
  3. destructor一定用noexcept
  4. 简单的leaf function,像是int,pointer这类的getter,setter用noexcept。因为不可能出错
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 22:43:27  更:2021-12-28 22:45:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:03:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码