[C++]函数

Posted jiangwei0512

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C++]函数相关的知识,希望对你有一定的参考价值。

参数传递

因为C++中引用的存在,所以参数分为了两类:引用传递:形参其实就是实参的一个别名;值传递:实参的值被拷贝给形参。C语言中一般都是值传递,包括指针其实也是值传递。为了避免大数据的拷贝,应该使用引用传递。

使用引用传递需要对const有进一步的了解。实参初始化形参时会忽略掉顶层的const。而如果形参本身就带有const,则传入的实参可以有const也可以没有const。如果引用没有带const,如下面的例子:

string::size_type find_char(string &s, char c,
    string::size_type &occurs)
{}

int main()
{
    auto index = find_char("Hello", 'o', ctr); // 报错

    return 0;
}

这里直接会报错。原因是引用不能赋值为字面值这样的不能改变的对象。为了解决这样的问题,就需要将形参改成const引用(当然这样就会导致它不可通过函数修改):

string::size_type find_char(const string &s, char c,
    string::size_type &occurs)

可变形参

C++可以使用C语言类似的可变形参,就是使用省略号“...”。还引入initializer_list,它是标准库类型,使用它需要增加如下的代码:

#include <initializer_list>
using std::initializer_list;

它提供了如下的操作:

一个示例:

void error_msg(initializer_list<string> il)
{
    for (auto beg = il.begin(); beg != il.end(); ++beg)
        cout << *beg << " " ;
    cout << endl;
}

返回值

C++中可以使用花括号包围的值的列表作为返回值。

C++中可以使用尾置返回类型:

auto func(int i) -> int(*)[10];  // use a trailing return type
// use trailing return type
auto getFcn(const string&) -> string::size_type(*)(const string&, const string&);

第一个返回指针,该指针指向有10个整数的数组;第二个返回函数指针。

decltype可以用于声明返回值类型。

函数重载

名字相同但是形参列表不同(数量或这类型不同)的函数,称为重载函数。注意不包括返回值。另外,前面已经说过顶层const会被形参忽略,所以只有顶层const不同也不算重载,但是底层const算重载。示例:

Record lookup(Phone*);
Record lookup(Phone* const);     // 顶层const,不算重载,报错。

Record lookup(Account&);
Record lookup(const Account&)    // 重载函数,作用于常量引用。

Record lookup(Account*);
Record lookup(const Account*);   //重载函数,作用于常量指针。

对于有常量和非常量的版本,编译器会优先选用非常量版本的重载函数。

默认实参

C++支持默认实参,就是在定义函数时对形参赋默认值:

typedef string::size_type sz;
string screen(sz ht = 24; sz wid = 60; char backgrnd = ' ');

这时在调用screen()函数时,就可以省略掉参数。但是需要注意,不能出现下面的情况:

screen(,,'*');  // 错误

上述用法是错误的,因为只能省略尾部的实参。

此外还需要说明,多次声明同一个函数是合法的,但是对于默认实参,在给定的作用域中一个形参只能被赋予一次默认实参。换句话说声明只能为之前那些没有默认值的形参添加默认实参,而不能改变原来的默认实参。示例:

void func(int = 10, int = 10);
void func(int a, int b)
{
    cout << a + b << endl;
}

int main()
{
    func();

    return 0;
}

这里的函数声明了一次,定义了一次,在声明的时候设置了默认值,要注意它的写法,并没有写形参变量,直接忽略掉了。在定义的时候就不能再写了,因为默认实参一旦确认,就不能再设置。

除了局部变量不能作为默认实参,其它只要表达式的类型能转换成形参所需要的类型,都可以作为默认实参。

内联函数和constexpr函数

内联函数用inline关键字声明,且一般包含在头部:

//inline version: find the shorter of two strings
inline const string &
shorterString(const string &s1, const string &s2)
{
    return s1.size() <= s2.size() ? s1 : s2;
}

内联机制用于优化规模较小、流程直接、频繁调用的函数。但是内联说明只是向编译器发出的一个请求,但是编译器可以选择忽略这个请求。

constexpr函数的返回值类型以及所有的形参都是字面值类型,而且函数体中必须有且只有一条return语句。示例:

constexpr int new_sz() { return 42; }

constexpr函数被隐式地指定为内联函数。constexpr函数一般也放在头文件中。

调试帮助

assert是预处理宏,格式:

#include <cassert>
assert(expr);

expr为假则assert输出信息并终止程序的执行。这还受另外的一个宏NDEBUG影响,如果它存在,则assert什么也不做。其它的宏定义:

__func__
__FILE__
__LINE__
__DATE__
__TIME__

下面是一个例子:

void print(const int ia[], size_t size)
{
#ifndef NDEBUG
    // __func__ is a local static defined by the compiler that holds the name of this function
    cerr << __func__ << ": array size is " << size << endl;
#endif
// . . .
}

int main()
{
    string word = "foo";
    const string::size_type threshold = 5;
    if (word.size() < threshold)
    cerr << "Error: " << __FILE__
        << " : in function " << __func__
        << " at line " << __LINE__ << endl
        << "       Compiled on " << __DATE__
        << " at " << __TIME__ << endl
        << "       Word read was \\"" << word
        << "\\":  Length too short" << endl;
    word = "something longer than five chars";
    assert(word.size() > threshold);

    return 0;
}

打印的结果: 

F:\\Codes\\cppprimer\\6>wdebug.exe
Error: wdebug.cc : in function main at line 63
       Compiled on May  4 2021 at 17:38:28    
       Word read was "foo":  Length too short 

其中的文件名、函数名、行数、日期和时间就是通过宏展开的。

以上是关于[C++]函数的主要内容,如果未能解决你的问题,请参考以下文章

2C++ 的升级

inline内联函数

这些 C++ 代码片段有啥作用?

有趣的 C++ 代码片段,有啥解释吗? [复制]

以下代码片段 C++ 的说明

C++ 代码片段执行