C++中函数使用的基本知识学习教程
|
函数是执行某种操作的代码块。函数可以选择性地定义使调用方可以将实参传递到函数中的输入形参。函数可以选择性地返回值作为输出。函数可用于在单个可重用块中封装常用操作(理想情况是使用可清晰地描述函数行为的名称)。以下函数从调用方接受两个整数并返回其总和;a 和 b 是 int 类型的参数。
int sum(int a,int b)
{
return a + b;
}
可以从程序中任意数量的位置调用函数。传递给函数的值是实参,其类型必须与函数定义中的形参类型兼容。
int main()
{
int i = sum(10,32);
int j = sum(i,66);
cout << "The value of j is" << j << endl; // 108
}
对于函数长度没有实际限制,不过良好的设计应以执行单个明确定义的任务的函数为目标。复杂算法应尽可能分解成易于理解的更简单函数。
constexpr float exp(float x,int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x,n / 2) :
exp(x * x,(n - 1) / 2) * x;
};
其 linkage 规范(extern 或 static)。 Declare printf with C linkage. extern "C" int printf( const char *fmt,... ); inline,指示编译器将对函数的每个调用替换为函数代码本身。在某个函数快速执行并且在性能关键代码段中重复调用的情况下,内联可以帮助提高性能。
inline double Account::GetBalance()
{
return balance;
}
noexcept,指定函数是否可以引发异常。在下面的示例中,函数在 is_pod 表达式计算结果为 true 时不引发异常。
#include <type_traits>
template <typename T>
T copy_object(T& obj) noexcept(std::is_pod<T>) {...}
仅限成员函数)cv 限定符,指定函数是 const 还是 volatile。 (仅限成员函数仅)应用于成员函数的 static 表示函数不与类的任何对象实例关联。
函数定义部分
template<typename Lhs,typename Rhs>
auto Add2(const Lhs& lhs,const Rhs& rhs)
{
return lhs + rhs;
}
auto a = Add2(3.13,2.895); // a is a double
auto b = Add2(string{ "Hello" },string{ " World" }); // b is a std::string
有关详细信息,请参阅函数模板
函数形参和实参
void DoSomething(std::string& input){...}
当函数修改通过引用传递的参数时,它会修改原始对象,而不是本地副本。若要防止函数修改这类实参,请将形参限定为
const&:
void DoSomething(const std::string& input){...}
C++ 11:若要显式处理通过右值引用或通过左值引用传递的实参,请对形参使用双与号以指示通用引用:
void DoSomething(const std::string&& input){...}
只要关键字 void 是实参声明列表中的第一个也是唯一一个成员,那么在形参声明列表中使用单个关键字 void 声明的函数就没有实参。列表中的其他地方的 void 类型的参数产生错误。例如: // OK same as GetTickCount() long GetTickCount( void ); 请注意,尽管指定 void 参数是非法(此处所述的除外),但派生自类型 void 的类型(如指向 void 的指针和 void 的数组)可以出现在参数声明列表中的任何位置。
int DoSomething(int num,string str,Allocator& alloc = defaultAllocator)
{ ... }
// OK both parameters are at end
int DoSomethingElse(int num,string str = string{ "Working" },Allocator& alloc = defaultAllocator)
{ ... }
// C2548: 'DoMore': missing default parameter for parameter 2
int DoMore(int num = 5,// Not a trailing parameter!
string str,Allocator& = defaultAllocator)
{...}
函数返回类型
template<typename Lhs,typename Rhs>
auto Add(const Lhs& lhs,const Rhs& rhs) -> decltype(lhs + rhs)
{
return lhs + rhs;
}
当 auto 与结尾返回类型结合使用时,它对于 decltype 表达式生成的任何内容都只用作占位符,本身不执行类型推导。
template<typename Lhs,const Rhs& rhs)
{
return lhs + rhs; //returns a non-const object by value
}
请注意,auto 不会保留它推导的类型的常量性。对于返回值需要保留其参数的常量性或引用性的转发函数,可以使用 decltype(auto) 关键字,该关键字使用 decltype 类型推断规则并保留所有类型信息。 decltype(auto) 可以用作左侧的普通返回值,或结尾返回值。
template<typename F,typename Tuple = tuple<T...>,int... I>
decltype(auto) apply_(F&& f,Tuple&& args,index_sequence<I...>)
{
return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
}
template<typename F,typename Indices = make_index_sequence<tuple_size<Tuple>::value >>
decltype( auto)
apply(F&& f,Tuple&& args)
{
return apply_(std::forward<F>(f),std::forward<Tuple>(args),Indices());
}
}
函数局部变量 typedef int (*fp)(int); fp myFunction(char* s); // function returning function pointer 如果不执行此操作,则函数声明的正确语法可以通过用函数名称和参数列表替换标识符(上例中为 fp)来从函数指针的声明符语法推导出,如下所示: int (*myFunction(char* s))(int); 前面的声明与使用上面的 typedef 的声明等效。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

