[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++]函数的主要内容,如果未能解决你的问题,请参考以下文章