• 突破编程_C++_面试(函数(1))


    面试题1:函数定义与声明有什么区别?

    函数定义与声明的区别主要体现在以下几个方面:
    内存分配:
    定义:函数定义会为函数分配内存空间,并且可能会为函数内部的局部变量分配内存。定义提供了函数在程序中的唯一描述,包括函数的实现细节,如函数体中的代码。
    声明:函数声明不会分配内存空间。它仅仅告诉编译器函数的名称、返回类型和参数类型,但不会提供函数的实际实现。
    实现与原型:
    定义:函数定义包含了函数的实现,即函数体中的代码,这是函数具体执行的操作。
    声明:函数声明通常称为函数原型,它提供了函数的签名,包括函数名、返回类型和参数列表,但不包括函数体。
    出现次数:
    定义:在C++程序中,函数的定义只能出现一次。如果尝试在多个地方定义相同的函数,会导致编译错误。
    声明:函数声明可以在程序中多次出现。通常,函数声明会放在头文件中,而定义会放在源文件中。这样,当其他文件包含这个头文件时,就可以使用这个函数,而不需要知道它的具体实现。
    作用域:
    定义:函数定义具有作用域,它定义了函数在程序中的可见性和可访问性。
    声明:函数声明也具有作用域,但它只是告诉编译器函数的存在和它的接口,而不涉及具体的实现。
    总结来说,函数定义提供了函数的完整实现,包括函数体中的代码,而函数声明则提供了函数的接口信息,包括函数名、返回类型和参数列表,但不包括函数体。在 C++ 程序中,函数定义只能出现一次,而函数声明可以多次出现,通常用于在其他文件中声明函数的存在和接口。

    面试题2:什么是函数重载?它有什么作用?

    函数重载( Function Overloading )是 C++ 中一种重要的编程特性,它允许在同一作用域内定义多个同名函数,但这些函数的参数列表(即参数的个数、类型或顺序)必须不同。通过函数重载,我们可以使用相同的函数名来表示不同的操作,从而提高代码的可读性和可维护性。
    函数重载的作用主要体现在以下几个方面:
    提高代码的可读性和可维护性
    重载函数使得程序员可以根据函数名来推测函数的功能,而不需要记住每个函数的具体细节。这有助于减少代码中的错误,并提高代码的可读性和可维护性。
    避免命名冲突
    通过函数重载,我们可以使用相同的函数名来表示不同的操作,而无需为每个操作创建不同的函数名。这有助于避免命名冲突,并使代码更加整洁和易于理解。
    提供更灵活的函数调用方式
    函数重载允许根据实际需求选择不同的函数。例如,我们可以根据参数的类型、个数或顺序来调用不同的函数,从而实现更灵活的函数调用方式。
    需要注意的是,函数重载并不是通过函数的返回值类型来区分的(在函数调用时,编译器需要根据提供的参数来确定应该调用哪个重载函数。如果允许通过返回值类型来重载函数,编译器在编译时可能无法确定应该调用哪个函数,因为返回值类型是在函数执行后才知道的。这会导致编译时的歧义和不确定性)。也就是说,如果两个函数的参数列表完全相同,但返回值类型不同,那么它们将被视为两个不同的函数,而不是重载函数。这是因为函数的返回值类型不参与函数调用的过程,因此不能作为区分重载函数的依据。
    总的来说,函数重载是 C++ 中一种非常有用的特性,它允许定义多个同名函数,并通过参数列表的不同来区分这些函数。这有助于提高代码的可读性和可维护性,避免命名冲突,并提供更灵活的函数调用方式。

    面试题3:什么是内联函数?为什么使用它?

    内联函数( Inline Function )是 C++ 中的一种特殊函数,它通过在编译时将函数体直接插入到函数调用点处,而不是通过常规的函数调用机制来执行。这样可以消除函数调用的开销,提高程序的执行效率。
    内联函数通常用于频繁执行的小函数,这些函数体代码较小,但调用次数很多。由于每次函数调用都会带来一定的开销,如参数传递、栈帧创建和销毁等,因此使用内联函数可以减少这些开销,提高程序的执行效率。
    内联函数的使用通过在函数定义前添加 inline 关键字来声明。然而,是否真正将函数内联展开是由编译器决定的,编译器会根据函数的实现和调用情况来决定是否进行内联展开。
    使用内联函数的好处主要包括:
    提高执行效率:通过消除函数调用的开销,内联函数可以提高程序的执行效率,特别是对于那些频繁执行的小函数。
    减少函数调用的开销:内联函数避免了函数调用的开销,包括参数传递、栈帧创建和销毁等,从而减少了程序的时间消耗。
    然而,使用内联函数也需要注意以下几点:
    代码膨胀:由于内联函数会将函数体直接插入到调用点处,这可能导致编译后的代码体积增大,从而可能增加缓存未命中的概率,降低程序的执行效率。
    不适用于复杂函数:内联函数通常只适用于简单的小函数,对于复杂的大型函数,内联可能会导致代码膨胀和编译时间增加。
    内联函数的声明和定义:内联函数必须在调用之前被声明或定义,否则编译器无法知道它是内联函数。同时,内联函数的定义通常放在头文件中,以便在多个源文件中共享。
    下面是一个简单的内联函数样例:

    #include   
      
    // 声明内联函数  
    inline int add(int x, int y) 
    {  
        return x + y;  
    }  
      
    int main() 
    {  
        // 调用内联函数  
        int result = add(1, 2);  
        std::cout << "the result is: " << result << std::endl;  
        return 0;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    由于 add 函数被定义为内联函数,编译器在编译时会尝试将 add 函数的调用替换为函数体的直接拷贝。这意味着在 main 函数中调用 add(1, 2) 时,编译器可能会直接将其替换为 return 1 + 2; ,从而消除函数调用的开销。

    面试题4:什么是 const 函数和 const 参数?

    const 函数
    const 函数是指那些不会修改任何成员变量的函数。也就是说, const 成员函数只能调用其他的 const 成员函数,并且不能修改任何类的成员变量(除非这些变量被声明为 mutable )。
    这样的函数通常在两种情况下使用:
    (1)不希望修改对象的状态:例如,你可能有一个代表矩形的类,该类有一个计算面积的方法。这个方法不应该修改矩形的任何属性(如长度或宽度),因此,它可以被声明为 const 。
    (2)对象是一个常量: const 修饰的对象只能调用该对象的 const 成员函数。
    下面是一个 const 函数的例子:

    class MyClass {  
    public:  
        int getVal() const 
    	{  
    		//m_val=2;		//错误: const 函数不能修改任何成员变量
            return m_val;  
        }  
      
    private:  
        int m_val;  
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这个例子中, getVal 函数是 MyClass 类的一个成员函数,并且被声明为 const 函数。由于 getVal 是 const 的,它不能修改类的任何成员变量(除非这些变量被声明为 mutable )。需要注意的是, const 函数并不意味着函数的返回值不能被修改。实际上, const 函数可以返回任何类型的值,包括可以被修改的类型。 const 关键字仅表示该函数不会修改调用它的对象的状态。
    const参数
    const 参数是指那些在函数体内不能被修改的参数。当将一个参数声明为 const 时,意味着这个参数在函数体内不会被修改,这有助于编译器进行更好的优化。
    此外, const 参数也可以提高代码的可读性和可维护性,因为它清晰地表明了这个参数在函数体内不会被修改。
    下面是一个使用 const 参数的例子:

    int getStrLength(const std::string& str) // const参数
    { 
        return str.length(); // 不能修改str
    }
    
    • 1
    • 2
    • 3
    • 4

    在这个例子中, str 是一个 const 引用参数,这意味着不能在 getStrLength 函数内部修改 str 。如果尝试这样做,编译器会报错。
    总结, const 函数和 const 参数都是 C++ 中重要的编程概念,它们有助于编写更安全、更可读的代码,并允许编译器进行更好的优化。

    面试题5:函数返回多个值的方法有哪些?

    在C++中,函数通常只能返回一个值。然而,有几种方法可以模拟函数返回多个值的情况:
    (1)使用结构体或类
    可以创建一个结构体或类来封装多个值,并将这个结构体或类作为函数的返回值。这样,函数就可以"返回"多个值,实际上是返回了一个包含多个值的对象。

    struct MyStruct 
    {
        int val1;
        double val2;
    };
    
    MyStruct getMultipleValues() 
    {
        MyStruct res;
        res.val1 = 1;
        res.val2 = 1.2;
        return res;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    (2)使用指针或引用
    可以通过指针或引用传递一个变量到函数中,让函数修改这个变量的值。此时,函数"返回"多个值的方式是通过修改这些变量的值。

    void getMultipleValues(char* val1, double& val2) 
    {
        *val1 = 1;
        val2 = 1.2;
    }
    
    int main() {
        int val1;
        double val2;
        getMultipleValues(val1, val2);
        // 现在 val1, val2 包含了函数返回的值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    (3)使用 std::tuple
    C++11 引入了 std::tuple ,它允许将不同类型的值组合在一起。可以返回一个 std::tuple ,并通过 std::tie 或解构赋值来获取返回值。

    #include 
    
    std::tuple<int, double> getMultipleValues()
    {
        return std::make_tuple(1, 1.2);
    }
    
    int main() {
        auto result = getMultipleValues();
        int val1;
        double val2;
        std::tie(val1, val2) = result;
        // 现在 val1, val2 包含了函数返回的值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    (4)使用 std::pair
    对于两个值的情况,可以使用 std::pair 。

    #include 
    
    std::pair<int, double> getMultipleValues() {
        return std::make_pair(1, 1.2);
    }
    
    int main() 
    {
        auto result = getMultipleValues();
        int val1 = result.first;
        double val2 = result.second;
        // 现在 val1, val2 包含了函数返回的值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    (5)使用 std::array 或 std::vector
    对于固定大小或可变大小的多个相同类型的值,可以使用 std::array 或 std::vector 。

    #include 
    
    std::array<int, 2> getMultipleValues() {
        return {1, 2};
    }
    
    int main() {
        auto res = getMultipleValues();
        int val1 = res[0];
        int val2 = res[1];
        // 现在 val1, val2 包含了函数返回的值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在实际编程中,选择哪种方法取决于具体的使用场景和个人偏好。 std::tuple 和 std::pair 通常用于返回不同类型值的场景,而结构体或类则更适合于返回逻辑上紧密相关的多个值。使用引用或指针作为输出参数可以避免额外的内存分配开销,但可能会使代码更难阅读和理解。

  • 相关阅读:
    使用id限定优化mysql分页查询limit偏移量大问题
    同事都说有SQL注入风险,我非说没有
    安装Ruby和安装Rails详细步骤详解
    论文 | REACT: SYNERGIZING REASONING AND ACTING INLANGUAGE MODELS
    ICML2021 | RSD: 一种基于几何距离的可迁移回归表征学习方法
    专利交底书怎么写 -
    Linux xfs文件系统stat命令Birth字段为空的原因探究
    Spring Data Envers 支持有条件变动纪录的保存和查询
    SQL 语句的执行顺序
    Oracle 插入数据
  • 原文地址:https://blog.csdn.net/h8062651/article/details/136194479