zoukankan      html  css  js  c++  java
  • 特殊用途语言特性

    默认实参

    默认形参声明

    在给定的作用域中,一个形参只能被赋予一次默认实参,这意味着在函数的多个声明中,只能为之前那些没有默认值的形参添加默认参数,而且该形参右侧的所有形参必须都有默认值。

    默认形参初始值

    局部变量不可以作默认实参,除此之外只要表达式的类型能转换成形参需要的类型,该表达式就可以作默认实参。

    int w = 80;
    char def = ' ';
    
    void test(int a = w, char c= def)
    {
    	cout << a << endl;
    	cout << c << endl;
    }
    
    int main()
    {
    	int w = 100;  //隐藏了外层定义的w,但是没有改变默认值
    	def = '*';  //会改变默认实参的值
    	test();
    
       return 0;
    }
    

    内联函数和 constexpr 函数

    调用函数比一般求等价表达式的值要慢一些,一次函数调用包含着一系列的工作:调用前要保存寄存器,并在返回时恢复;可能需要拷贝实参;程序转向新的位置执行。

    内联函数可以避免函数调用的开销,通常就是将它在每个调用点上“内联的”展开。

    inline const string &shorterString(const string &str1, const string &str2)
    {
    	return str1.size() <= str2.size() ? str1 : str2;
    }
    

    调用时:

    cout<<shorterString(s1,s2)<<endl;
    

    在编译的过程中展开成类似下面的形式:

    cout<<str1.size() <= str2.size() ? str1 : str2<<endl;
    
    

    注意:

    • 内联声明只是想编译器发出一个请求,编译器可以选择忽略这个请求。
    • 内联机制一般用于优化规模较小、流程直接、频繁调用的函数。
    • 很多编译器不支持内联递归函数。

    constexpr

    constexpr 函数是指用于常量表达式的函数。

    定义 constexpr 函数:

    • 函数的返回类型以及所有的形参类型都得是字面值类型。
    • 函数体内有且只有一条return 语句。
    constexpr int new_sz(){	return 42;}
    
    int main()
    {
       constexpr int foo = new_sz();
       return 0;
    }
    

    new_sz 没有参数,编译器在程序编译时会验证 new_sz 函数返回的是不是常量表达式,所以可以使用 new_sz 函数初始化 constexpr 类型的变量。

    执行该初始化任务时,编译器把对 constexpr 函数的调用结果替换成其结果值,为了能够在编译过程中随时展开, constexpr 函数被隐式地指定为内联函数。

    注意:

    • constexpr 函数返回的不一定是常量表达式:
    constexpr size_t scale(size_t cnt) {return new_sz() * cnt};
    

    如果scale 的实参是常量表达式,那么它的返回值也是常量表达式,反之则不然:

    int arr[scale(2)]; //正确,scale(2)是常量表达式
    int i = 2;	// i 不是常量
    int a2[sclae(i)]; //错误,scale(i)不是常量表达式
    
    • constexpr 函数体内也可以包含其他语句,只要这些语句不执行任何操作就行,例如:空语句,类型别名,using 声明。

    调试帮助

    assert 预处理宏

    assert 是一种预处理宏,所谓的预处理宏其实就是一个预处理变量,它的行为类型于内联函数,assert 宏使用一个表达式作为条件:

    assert(expr);
    
    • 首先会对 expr 求值,如果表达式为假,assert 输出信息并终止程序的执行,如果表达式为真,assert 什么也不做。
    • assert 宏定义在 cassert 头文件中,预处理器的名字由预处理器而非编译器管理。
    • 和预处理变量一样,宏名字在程序中必须唯一,含有 cassert 头文件的程序不能再定义名为 assert 的变量、函数或者其它实体。
    • assert 宏通常是用来检查不能发生的条件。
    • assert 宏可以作为一种调试程序的辅助手段,但是不能用它替代真正的运行时逻辑检查,也不能替代程序本身应该包含的错误检查。

    NDEBUG预处理变量

    assert 的行为依赖于一个名为 NDEBUG 的预处理变量的状态,如果定义了 NDEBUG ,则 assert 什么也不做。默认情况是没有定义 NDEBUG

    C++ 预处理中定义的对于程序调试很有用的名字:

    • __func__ :存放当前调试函数的名字。
    • __FILE__ :存放当前文件名的字符串字面值。
    • __LINE__ :存放当前行号的整型字面值。
    • __TIME__ :存放文件编译时间的字符串字面值。
    • __DATE__ :存放文件编译日期的字符串字面值。
  • 相关阅读:
    Linux常用命令之 查找命令 find —— 细说 -atime,-mtime,-ctime
    centos设置静态ip
    Linux中vim的基本操作
    Linux中/和~的区别
    Linux安装vmtools工具
    关于 [lambda x: x*i for i in range(4)] 理解
    Ubuntu虚拟环境的搭建
    tomcat的中的Apache的apr是个啥东东???
    什么是web资源????
    Handlebars学习第一天
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/12498116.html
Copyright © 2011-2022 走看看