C++PrimerPlus学习笔记之函数探幽-创新互联

前言

个人觉得学习编程最有效的方法是阅读专业的书籍,通过阅读专业书籍可以构建更加系统化的知识体系。
一直以来都很想深入学习一下C++,将其作为自己的主力开发语言。现在为了完成自己这一直以来的心愿,准备认真学习《C++ Primer Plus》。
为了提高学习效率,在学习的过程中将通过发布学习笔记的方式,持续记录自己学习C++的过程。

创新互联-专业网站定制、快速模板网站建设、高性价比天水网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式天水网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖天水地区。费用合理售后完善,10多年实体公司更值得信赖。一、C++内联函数

内联函数是C++为提高程序运行速度所做的一项改进。常规函数和内联函数之间的主要区别不在于编写方式,而在于C++编译器如何将它们组合到程序中。

对于内联代码,程序无需跳到另一个位置处执行代码,再跳回来。因此,内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存。如果程序在10个不同的地方调用同一个内联函数,则该程序将包含该函数代码的10个副本。

要使用这项特性,必须采取下述措施之一:

  • 在函数声明前加上关键字inline
  • 在函数定义前加上关键字inline
    通常的做法是省略原型,将整个定义(即函数头和所有函数代码)放在本应提供原型的地方
二、引用变量

C++新增了一种复合类型——引用变量。引用是已定义的变量的别名(另一个名称)。

C和C++使用&符号来指示变量的地址。C++给&符号赋予了另一个含义,将其用来声明引用。例如,要将rodents作为rats变量的别名,可以这样做:

int rats;
int & rodents = rats;

int &指的是指向int的引用。

引用经常被用作函数参数,使得函数中的变量名成为调用程序中的变量的别名。这种传递参数的方法称为按引用传递。按引用传递允许被调用的函数能够访问调用函数中的变量。

如果意图是让函数使用传递给它的信息,而不对这些信息进行修改,同时又想使用引用,则应使用常量引用:

double refcube(const double &ra);

如果实参与引用参数不匹配,C++将生成临时变量。当前,仅当参数为const引用时,C++才允许这样做,但以前不是这样。

如果引用参数是const,则编译器将在下面两种情况下生成临时变量:

  • 实参的类型正确,但不是左值;
  • 实参的类型不正确,但可以转换为正确的类型。

**左值参数:**是可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。

**非左值:**包括字面常量(用引号括起的字符串除外,它们由其地址表示)和包含多项的表达式。在C语言中,左值最初指的是可出现在赋值语句左边的实体,但这是引入关键字const之前的况。现在,常规变量和const变量都可视为左值,因为可通过地址访问它们。但常规变量属于可修改的左值,而const变量属于不可修改的左值。

将引用参教声明为常量数据的引用的理由有三个:

  • 使用const可以避免无意中修改数据的编程错误;
  • 使用const使函数能够处理const和非const实参,否则将只能接受非const数据;
  • 使用const引用使函数能够正确生成并使用临时变量。

C++11新增了另一种引用——右值引用(rvalue reference)。这种引用可指向右值,是使用&&声明的:

double && rref = std::sqrt(36.00);

新增右值引用的主要目的是,让库设计人员能够提供有些操作的更有效实现。

引用非常适合用于结构和类(C++的用户定义类型)。

返回引用的函数实际上是被引用的变量的别名。

返回引用时最重要的一点是,应避免返回函数终止时不再存在的内存单元引用。为避免这种问题,最简单的方法是,返回一个作为参数传递给函数的引用。另一种方法是用new来分配新的存储空间。

使得能够将特性从一个类传递给另一个类的语言特性被称为继承。

继承的另一个特征是,基类引用可以指向派生类对象,而无需进行强制类型转换。

使用引用参数的主要原因有两个:

  • 程序员能够修改调用函数中的数据对象。
  • 通过传递引用而不是整个数据对象,可以提高程序的运行速度。

对于使用传递的值而不作修改的函数。

  • 如果数据对象很小,如内置数据类型或小型结构,则按值传递。
  • 如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明指向const的指针。
  • 如果数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率。这样可以节省复制结构所需的时间和空间。
  • 如果数据对象是类对象,则使用const引用。类设计的语义常常要求使用引用,这是C++新增这项特性的主要原因。因此,传递类对象参数的标准方式是按引用传递。

对于修改调用函数中数据的函数:

  • 如果数据对象是内置数据类型,则使用指针。如果看到诸如txi(&x)这样的代码(其中×尼imnt)则很明显,该函数将修改x。
  • 如果数据对象是数组,则只能使用指针。
  • 如果数据对象是结构,则使用引用或指针。
  • 如果数据对象是类对象,则使用引用。
    当然,这只是一些指导原则,很可能有充分的理由做出其他的选择。
三、默认参数

默认参数指的是当函数调用中省略了实参时自动使用的一个值。

char * left(const char * str, int n = 1);

对于带参数列表的函数,必须从右向左添加默认值。也就是说,要为某个参数设置默认值,则必须为它右边的所有参数提供默认值。

四、函数重载

函数多态是C++在C语言的基础上新增的功能。术语“多态”指的是有多种形式,因此函数多态允许函数可以有多种形式。类似地,术语“函数重载"’指的是可以有多个同名的函数,因此对名称进行了重载。这两个术语指的是同一回事,但我们通常使用函数重载。

函数重载的关键是函数的参数列表——也称为函数特征标(function signature)。编译器在检查函数特征标时,将把类型引用和类型本身视为同一个特征标。

五、函数模板

函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体地类型(如int 或 double)替换。由于类型是用参数表示的,因此模板特性有时也被称为参数化类型。

templatevoid Swap(AnyType &a, AnyType &b)
{AnyType temp;
    temp = a;
    a = b;
    b = temp;
}

关键字templatetypename是必需的,除非可用使用关键字class代替typename。另外,必须使用尖括号。

在标准C++98添加关键字typename之前,C++使用关键字class来创建模板。也就是说,可以这样编写模板定义:

templatevoid Swap(AnyType &a, AnyType &b)
{
    AnyType temp;
    temp = a;
    a = b;
    b = temp;
}

可以提供一个具体化函数定义——称为显式具体化(explicit specialization),其中包含所需的代码。

C++98标准选择了下面的具体化方法:

  • 对于给定的函数名,可以有非模板函数、模板函数和显式具体化模板函数以及它们的重载版本。
  • 显示具体化的原型和定义应以template<>打头,并通过名称来指出类型。
  • 具体化优先于常规模板,而非模板函数优先于具体化和常规模板。
template<>void Swap(job & , job &);

为进一步了解模板,必须理解术语实例化和具体化。记住,在代码中包合函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成明数定义时,得到的是模板实例(instantiation)。这种实例化方式被称为隐式实例化(implicit instantiation)。

现在C++还允许显式实例化(explicit instantiation):

template void Swap(int, int);

与显式实例化不同的是,显式具体化使用下面两个等价的声明之一:

template<>void Swap(int &, int &);
template<>void Swap(int &, int &);

区别在于,这些声明的意思是“不要使用Swap()模板来生成函数定义,而应使用专门为int类型显式地定义的函数定义”。这些原型必须有自己的函数定义。

显式具体化声明在关键字template后包含<>,而显式实例化没有。

完全匹配允许的无关紧要的转换:

从实参到形参
TypeType &
Type &Type
Type []* Type
Type(argument-list)Type (*)(argument-list)
Typeconst Type
Typevolatile Type
Type *const Type
Type *volatile Type *

指向非const数据的指针和引用]优先与非const指针和引用参数匹配。

其中一个是非模板函数,而另一个不是。在这种情况下,非模板函数将优先于模板函致(包括显式具体化)。

如果两个完全匹配的函数都是模板函数,则较具体的模板函数优先。

templatevoid ft(T1 x, T2 y)
{?type? xpy = x + y;
}

以上代码中xpy的类型无法明确,可以通过C++11新增关键字decltype来解决:

templatevoid ft(T1 x, T2 y)
{decltype(x + y) xpy = x + y;
}
template?type? ft(T1 x, T2 y) 
{return x + y;
}

以上代码中返回类型无法明确,可以通过auto关键字和关键字decltype组合使用来解决:

templateauto ft(T1 x, T2 y) ->decltype(x + y)
{return x + y;
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网站栏目:C++PrimerPlus学习笔记之函数探幽-创新互联
分享网址:http://scyanting.com/article/piocd.html