C++

C++ 知识量:19 - 82 - 316

6.1 函数基础><

函数- 6.1.1 -

在C++中,函数是一种可重用的代码块,它可以被程序中的其他部分调用。以下是一个基本的C++函数的定义和用法:

// 函数定义  
int add(int a, int b) {  
    return a + b;  
}  
  
// 函数调用  
int main() {  
    int sum = add(5, 3);  // 调用上面定义的add函数,并将结果存储在sum变量中  
    std::cout << "The sum is: " << sum << std::endl;  // 输出结果  
    return 0;  
}

在这个例子中,add是一个函数,它接收两个整数参数(a和b),并返回它们的和。在main函数中,调用了add函数,并将结果存储在sum变量中,然后输出这个结果。

C++函数可以具有各种不同的参数类型和返回类型,包括基本数据类型(如int、float、double、char等),也可以是用户定义的数据类型(如结构体、类等)。函数也可以没有返回值(在这种情况下,返回类型通常为void)。

形参和实参- 6.1.2 -

在C++中,形参(Parameter)和实参(Argument)是函数调用中的重要概念。

形参是在定义函数时声明的参数,它们在函数体内使用。形参列表包括每个参数的类型和名称。例如:

void myFunction(int a, float b) {  
    // 在这里,a 和 b 是形参  
}

实参是在调用函数时传递给函数的参数。实参可以是常量,变量,表达式或其他值。例如:

myFunction(5, 3.14);  // 这里,5 和 3.14 是实参

在函数调用时,实参必须与形参类型相匹配,且必须按照函数定义中参数的顺序传递。在函数体内,形参可以作为常量使用,也可以通过赋值或函数调用改变其值,但注意不能通过形参改变实参的值。这是因为在C++中,参数传递默认是按值传递,即创建了实参的副本。如果希望通过函数改变实参的值,可以使用指针或引用作为参数。

局部变量- 6.1.3 -

在C++中,局部变量是在函数或代码块内部定义的变量。它们只能在其所在的函数或代码块中可见,一旦离开该范围,它们就不再存在。

局部变量在它们被声明的代码块中有效。当代码块执行时,局部变量被创建,并在代码块结束时销毁。这意味着它们只能在此代码块中使用,不能在其他地方使用。

例如:

#include <iostream>  
  
int main() {  
    int a = 10;  // 局部变量  
    {  
        int b = 20;  // 另一个局部变量  
        std::cout << a << " " << b << std::endl;  
    } // b 在此处结束生命周期  
    std::cout << a << std::endl; // a 的生命周期延续到此  
    return 0;  
}

在这个例子中,a和b都是局部变量。a在主函数内部定义,而b在代码块内部定义。在代码块结束时,b被销毁,但a的生命周期延续到主函数的结尾。因此,输出将是:

10 20      
10

自动对象- 6.1.4 -

在C++中,自动对象是指那些在函数或代码块内部定义的变量。这些对象只存在于它们被声明的代码块或函数的执行期间。当代码块或函数执行完毕后,这些对象就会被销毁。

当函数或代码块被调用时,自动对象在内存中创建,并在该函数或代码块执行期间保持存在。这些对象的生命周期与它们所在的函数或代码块的执行期间相同。当函数或代码块执行完毕时,这些对象的生命周期也就结束了,内存空间将被释放。

自动对象的销毁顺序与它们的定义顺序相反。也就是说,最后一个被声明的自动对象将最先被销毁。这种销毁顺序也被称为LIFO(后进先出)原则。

自动对象的一个主要特点是它们不会在函数或代码块之间共享。也就是说,每个函数或代码块都有自己独立的自动对象集合。这些对象只在该函数或代码块的执行期间存在,因此不能在其他函数或代码块中使用。

需要注意的是,如果在函数或代码块内部定义了自动对象,但没有对其进行初始化,那么这些对象的值将是未定义的。因此,在使用这些对象之前,应该对其进行初始化或赋值。

局部静态对象- 6.1.5 -

在C++中,局部静态对象是指在函数内部定义的静态对象。这些对象在函数首次被调用时创建,并在程序的整个生命周期内存在。

局部静态对象的初始化时机是在其所在函数被调用时,而不是在程序启动时。因此,它们可以保留在函数调用之间的状态。当函数再次被调用时,这些对象会继续保留它们的状态,而不是重新创建新的对象。

与自动对象不同,局部静态对象不会在函数返回时销毁。相反,它们在程序结束时销毁。因此,局部静态对象可以在函数调用之间保留状态,并且可以在程序的生命周期内持续存在。

下面是一个示例代码,演示了局部静态对象的创建和使用:

#include <iostream>  
  
void func() {  
    static int count = 0;  // 局部静态对象  
    count++;  
    std::cout << "Count: " << count << std::endl;  
}  
  
int main() {  
    func();  // 输出:Count: 1  
    func();  // 输出:Count: 2  
    func();  // 输出:Count: 3  
    return 0;  
}

在这个例子中,func函数内部定义了一个静态整数变量count。每次调用func函数时,count的值都会增加,并输出当前的计数器值。由于count是一个局部静态对象,因此它会在程序的生命周期内一直存在,并保留它的状态。

函数声明- 6.1.6 -

在C++中,函数声明(或函数原型)是告诉编译器函数名称、返回类型以及参数列表的方式。如果在一个源文件中定义了一个函数,并在另一个源文件中使用该函数,那么需要在第二个源文件中包含函数声明,以便编译器知道如何调用该函数。

以下是一个C++函数声明的例子:

// 这是函数声明  
int add(int a, int b);  
  
// 这是函数定义  
int add(int a, int b) {  
    return a + b;  
}

在这个例子中,int add(int a, int b); 是函数声明,它告诉编译器有一个名为 add 的函数,该函数接受两个 int 类型的参数,并返回一个 int 类型的结果。

请注意,函数声明也可以包含参数默认值,例如:

// 这是函数声明,其中两个参数都有默认值  
void print_message(const char* message = "Hello, world!", int count = 1);

在这个例子中,如果调用 print_message() 时没有提供参数,那么将使用默认的参数值。对于 message 参数,默认值是 "Hello, world!",对于 count 参数,默认值是 1。

分离式编译- 6.1.7 -

分离式编译(separate compilation)是一种编译程序的方法,它允许将程序分割到多个文件中,每个文件可以独立编译。在C++语言中,分离式编译是通过将程序划分为多个源文件来实现的。每个源文件都可以独立编译,然后通过链接器将它们组合成一个可执行程序。

分离式编译可以提高编译速度和代码可维护性。由于每个源文件可以独立编译,因此可以并行编译多个文件,从而加快编译速度。此外,分离式编译还可以使代码更容易理解和维护。通过将代码划分为多个文件,可以清晰地定义程序的逻辑关系和模块化结构,使代码更易于阅读、修改和维护。

在C++中,分离式编译通常按照以下步骤进行:

  1. 将程序划分为多个源文件(.cpp),每个文件包含程序的某个模块或功能的代码。

  2. 为每个源文件编写头文件(.h或.hpp),其中包含该源文件的声明和定义。

  3. 在主编译单元(通常是main.cpp)中包含所有必要的头文件,以便在程序中引用其他文件中的函数和类。

  4. 使用C++编译器将每个源文件独立编译为目标文件(.o),例如使用g++命令:g++ -c sourcefile.cpp。

  5. 使用链接器将目标文件组合成一个可执行程序,例如使用g++命令:g++ main.o sourcefile1.o sourcefile2.o -o program。

通过这种方式,可以将大型程序划分为多个较小的源文件,使编译过程更高效,同时提高代码的可维护性和可读性。