【C++ grammar】重载、内联、变量作用域、带默认参数的函数

1、变量的作用域

1. 变量的作用域分类

a. 全局作用域:全局变量
b. 局部作用域:局部变量

局部作用域可以分为:文件作用域、函数作用域以及函数内部的块作用域。

如果外部代码块与其内嵌代码块有同名的变量,那么会产生同名覆盖这种现象。此时要遵循“就近原则”来判断哪个同名变量起作用

例如下面func2中,for循环中又定义了一个i,在运行sum+=i;时根据就近原则,选择for定义的i,而不是一开始定义的i。

在cout中的i是一开始定义的i,因为已经跳出for循环了。
在这里插入图片描述

2. Unary Scope Resolution (一元作用域解析运算符)

If a local variable name is the same as a global variable name, you can access the global variable using ::globalVariable. (局部变量名与全局变量名相同时,可使用 :: 访问全局变量,要定义在主函数外部)

The :: operator is known as the unary scope resolution.(:: 这个运算符被称为一元作用域解析运算符)

#include <iostream>
int v1 = 10;
int main() {
    
    
    int v1 = 5;
    std::cout << "local variable v1 is " << v1 << std::endl;
    std::cout << "global variable v1 is " << ::v1 << std::endl;
    return 0;
}

在这里插入图片描述

2、重载函数

重载函数是在同一个名字空间中存在两个或者多个具有相同名字的函数所构成的语法现象。
调用重载函数的语句,是由编译器在编译期确定的。
编译器判断某个函数调用语句所对应的重载函数时,判断依据是函数参数的类型、个数和次序。
如果编译器无法判定,就会报告二义性错误。

扫描二维码关注公众号,回复: 11946655 查看本文章

3、带有默认参数值的函数

函数的参数可以指定默认值。
指定默认值时,要保证带有默认值的参数要位于函数参数列表的右侧。
如下:
在这里插入图片描述
调用带有默认参数值的函数时,如果不指定带有默认值的参数,则该参数自动被赋为默认值。且调用的时候应该实参前置。
在这里插入图片描述

C++规定(C++03/C++11): A default argument shall not be redefined by a later declaration (not even to the same value). (函数重定义/声明时,不允许重定义默认参数)
int Add (int a, int b = 3); // 原型声明
int Add (int a, int b = 3) { // 错误!不能重定义默认参数值,
// 尽管与原型声明相同
}
如下:

#include <iostream>
void printArea(double radius = 1);
int main()
{
    
    
    printArea();
    printArea(4);
    return 0;
}
void printArea(double radius)
{
    
    
    std::cout << "Area is " << radius*radius*3.14 << std::endl;
}

在这里插入图片描述

4、重载函数 VS 带有默认参数值的函数

此时不能判断调用的是哪个函数。
在这里插入图片描述

5、内联函数(Inline Function)

1. 普通函数的优缺点

1.1. Pros(优点): 易读易维护

1.2. Cons (缺点): 调用时有开销

函数调用时:参数及部分CPU寄存器的内容进栈,控制流跳转

函数返回时:返回值及寄存器值出栈,控制流跳转

2. 使用内联函数

目的:减小函数调用开销

方法:代码插入到调用处

结果:导致程序变大

3. 定义内联函数

定义函数时,在函数类型前面加上 inline 关键字,则该函数就成为内联函数。

一般而言,内联函数的声明和定义都在一起。我们很少将内联函数的声明和定义分开编写。

// 定义内联函数

inline int max (int a, int b) {
    
    

    return (a > b ? a : b);

}
// Calling (调用内联函数)

int  x = max (3, 5);

int  y = max (0, 8);

 

// Inline expansion(内联展开)

int  x = (3 > 5 ? 3 : 5);

int  y = (0 > 8 ? 0 : 8);

4. 内联函数的使用

编译器在遇到内联函数的调用时,会将内联函数的函数体展开到调用位置,从而避免函数调用的开销。

一般来说,内联函数只有在需要考虑程序运行性能的环境中才使用。

程序员所用的 inline 关键字,只是对编译器的一个请求。内联函数是否展开,是由编译器决定的。

5. 将内联函数的声明和定义分离

在C++标准7.1.2.4节有如下说明

An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case (3.2). [ Note: A call to the inline function may be encountered before its definition appears in the translation unit. —end note ]

内联函数应在每个翻译单元中定义。在该翻译单元中它遵循“单一定义规则(ODR)”,并且所有该内联函数定义必须完全相同。[注释:在翻译单元中可能会在内联函数定义出现之前就有调用该内联函数的语句]

因此,内联函数声明和定义分类的用法如下:

#include <iostream>

inline void foo();

int main() {
    
    

  foo();

}

inline void foo() {
    
    

  std::cout << "Hi\n";

}

6. 内联函数使用限制

适用于频繁调用的短函数 不适用于多处调用的长函数

内联函数只是一种编译机制

inline是对编译器的请求,而不是命令

大多数编译器并不把带有循环、递归、静态变量或者代码较多的函数进行内联编译

猜你喜欢

转载自blog.csdn.net/qq_42604176/article/details/109095624