C++中的函数

1、C++内联函数

内联函数是C++为提高运行速度所做的一项改进。内联函数在函数声明前加上关键字inline,在函数定义前加上关键字inline。

1.1 内联函数与宏

inline工具是C++新增的特性。C语言使用预处理器语句#define来提供宏——内联代码的原始实现。

定义一个宏:#define  SQUARE(X)  X*X

这并不是通过传递参数实现的,而是通过文本替换来实现的——X是“参数”的符号标记。

a=SQUARE(5.0);    替换成 a=5.0*5.0;

b=SQUARE(4.5+7.5);  替换成b=4.5+7.5*4.5+7.5;

d=SQUARE(C++);    替换成d=C++*C++;

上述示例只有第一个能正常工作。可以通过使用括号来进行改进:

#define  SQUARE(X)  ((X)*(X))

但是仍然存在这样的问题,即宏不能按值传递。即使使用新的定义,SQUARE(C++)仍将C递增两次。

内联函数:

inline double square(double x) {return x*x; }

2、引用

#include <iostream>
#include <string>

struct free_throws
{
	std::string name;
	int made;
	int attempts;
	float percent;
};

//传递引用,不允许更改结构内容
void display(const free_throws& ft);
void set_pc(free_throws& ft);
free_throws& accumulate(free_throws& target, const free_throws& source);

int main()
{
	free_throws one = { "Ifelsa Branch", 13, 14 };
	free_throws two = { "Andor Knott",10,16 };
	free_throws three = { "Minnie Max",7,9 };
	free_throws four = { "Whily Lopper",5,9 };
	free_throws five = { "Long Long",6,14 };
	free_throws team = { "Throwgoods",0,0 };
	free_throws dup;

	set_pc(one);
	display(one);
	accumulate(team,one);
	display(team);
	dup = accumulate(team, five);

	std::cout << "Display team:\n";
	display(team);
	std::cout << "Displaying dup after assignment:\n";
	display(dup);
	set_pc(four);

	accumulate(dup,five)=four;
	std::cout << "Displaying dup after ill-advised assignment:\n";
	display(dup);

	std::cin.get();
	return 0;
}

void display(const free_throws& ft)
{
	std::cout << "Name: " << ft.name << std::endl;
	std::cout << "-Made: " << ft.made << '\t';
	std::cout << "Attempts: " << ft.attempts << '\t';
	std::cout << "Percent: " << ft.percent << '\n';
}

void set_pc(free_throws& ft)
{
	if (ft.attempts != 0)
		ft.percent = 100.0f*float(ft.made) / float(ft.attempts);
	else
		ft.percent = 0;
}

free_throws& accumulate(free_throws& target, const free_throws& source)
{
	target.attempts += source.attempts;
	target.made += source.made;
	set_pc(target);

	return target;
}

运行结果:

C++中的函数

 程序中的语句:

accumulate(dup,five)=four;

这条语句将赋值给函数调用,这是可行的,因为函数的返回值是一个引用。如果函数accumulate()按值返回,这条语句不能通过编译。由于返回的是指向dup的引用,因此上述代码与下面的代码等效:

accumulate(dup,five);

dup=four;

2.1 为什么要返回引用

free_throws dup;

dup=accumulate(team,five);

如果accumulate()返回一个结构,而不是指向结构的引用,将把整个结构复制到一个临时位置,再将这个拷贝给dup。但在返回值为引用时,将直接把team复制到dup,其效率更高。

返回引用时应该避免返回函数终止时不再存在的内存单元引用。应该避免下面这样的代码:

const free_throws& clone2(free_throws& ft)

{

        free_throws newguy;

        newguy=ft;     //拷贝赋值

        return newguy;

}

该函数返回一个指向临时变量(newguy)的引用,函数运行完毕后它将不再存在。

3、函数重载

函数重载能够使用多个同名的函数,函数重载的关键是函数参数列表——也称为函数特征标。如果两个函数的参数数目和类型相同,同时参数的排列顺序也相同,则它们的特征标相同,而变量名是无关紧要的,C++允许定义名称相同的函数,条件是他们的特征标不同。

4、函数模板

函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体的类型替换,通过将类型作为参数传递给模板,课时编译器生成该类型的函数。函数模板不能缩短可执行程序,最终的代码不包含任何模板,而只包含了为程序生成的实际函数。使用模板的好处是,它使生成多个函数定义更简单、更可靠。

更常见的形式是将模板放在头文件中,并在需要使用模板的文件中包含头文件。

4.1 重载模板

需要多个对不同类型使用同一种算法的函数时,可使用模板。和常规重载一样,被重载的模板的函数特征值必须不同。

4.2 显式具体化

提供一个具体化函数定义——称为显式具体化,其中包含所需的代码。当编译器找到与函数调用匹配的具体化定义时,将使用该定义,而不再寻找模板。

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

下面是用于交换结构的非模板函数、模板函数和具体化的原型:

struct job
	{
		char name[40];
		double salary;
		int floor;
	};

	void Swape(job&, job&);   //非模板函数

	template <typename T>
	void Swap(T&, T&);   //模板函数

	template <> void Swap<job>(job&, job&);  //具体化原型

编译器在选择原型时,非模板版本优于显式具体化和模板版本,而显式具体化优于使用模板生成的版本。

关键字decltype(C++11)

C++11新增的关键字decltype确定变量的类型。

template <class T1, class T2>

void ft(T1 x, T2 y)

{

        decltype(x+y) xpy=x+y;

}

上一篇:[TcaplusDB知识库]TcaplusDB的高可用性和数据安全性介绍


下一篇:C++内存管理