函数指针:
#include <iostream>
#include <array>
#include <string>
using namespace std;
double add(double, double);
//double (*pf)(double, double);
double calculate(double,double,double (*pf)(double,double));
int main() {
//double (*pf)(double, double) = add;
double res = calculate(3.4,4.5,add);
cout << res << endl;//7.9
return 0;
}
double add(double a, double b) {
return a + b;
}
double calculate(double a,double b,double (*pf)(double,double)) {
return (*pf)(a,b);
}
内联函数:
#include <iostream>
using namespace std;
//内联函数
inline int add(int a,int b){
return a+b;
}
int main() {
cout << add(2,3) << endl;
return 0;
}
引用
void test_create_ref(){
//1. 引用变量的声明
int num = 100;
//int & p;// error: 'p' declared as reference but not initialized
int & p = num;
//可以认为 p 就是 num,保存的都是变量的值
//可以认为 &p 就是 &num,保存的都是变量的地址
cout << p << endl;//100
cout << &p << endl;//0x63ff08
p++;
cout << num << endl;//101
//cout << &p << endl;//0x63ff08
cout << p << endl;//101
cout << &num << endl;//0x63ff08
}
将引用变量作为参数(交换两个数的实现):
#include <iostream>
using namespace std;
//2. 将引用变量作为参数
void swap1(int a, int b);
void swap2(int &a, int &b);
void swap3(int *a, int *b);
int main() {
int a = 3, b = 4;
swap1(a, b);
cout << a << " " << b << endl;
int & p1 = a;
int & p2 = b;
swap2(p1,p2);
cout << a << " " << b << endl;
int * p3 = &a;
int * p4 = &b;
swap3(p3,p4);
cout << a << " " << b << endl;
return 0;
}
//1. 交换两个数并不会成功
void swap1(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
//2. 通过引用交换两个数
//将主函数变量的地址传递过来
void swap2(int &a, int &b) {
int temp;
temp = a;
a = b;
b = temp;
}
//3. 通过指针交换两个数
void swap3(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
引用的属性和特别之处:
#include <iostream>
using namespace std;
int main() {
double a = 3;
cout << a << "^3=" << cube(a) << endl;//3^3=27
double res = refcube(a);//refcube函数修改了a的值
cout << a << endl;//27
cout << res << endl;//27
//double res2 = refcube(a+3); 编译错误--不能将double 赋值给非-const 的类型为double&的引用
//cannot bind non-const lvalue reference of type 'double&' to an rvalue of type 'double'
return 0;
}
//引用的属性和特别之处
double cube(double a) {
a *= a * a;
return a;
}
double refcube(double &ra) {
ra *= ra * ra;
return ra;
}
引用用于结构:
#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 Looper", 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);
// use return value as argument
display(accumulate(team, two));
accumulate(accumulate(team, three), four);
display(team);
// use return value in assignment
dup = accumulate(team,five);
std::cout << "Displaying team:\n";
display(team);
std::cout << "Displaying dup after assignment:\n";
display(dup);
set_pc(four);
// ill-advised assignment
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)
{
using std::cout;
cout << "Name: " << ft.name << '\n';
cout << " Made: " << ft.made << '\t';
cout << "Attempts: " << ft.attempts << '\t';
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;
}
/**返回结果如下:
Name: Ifelsa Branch
Made: 13 Attempts: 14 Percent: 92.8571
Name: Throwgoods
Made: 13 Attempts: 14 Percent: 92.8571
Name: Throwgoods
Made: 23 Attempts: 30 Percent: 76.6667
Name: Throwgoods
Made: 35 Attempts: 48 Percent: 72.9167
Displaying team:
Name: Throwgoods
Made: 41 Attempts: 62 Percent: 66.129
Displaying dup after assignment:
Name: Throwgoods
Made: 41 Attempts: 62 Percent: 66.129
Displaying dup after ill-advised assignment:
Name: Whily Looper
Made: 5 Attempts: 9 Percent: 55.5556
**/
//返回引用时需要注意的问题:避免返回函数终止时不存在的内存单元引用
const free_throws & clone2(free_throws & ft){
free_throws newguy;//newguy 在函数运行完毕后它将不再存在。
//warning: reference to local variable 'newguy' returned [-Wreturn-local-addr]
newguy = ft;
return newguy;//return reference to copy
}
将引用用于类对象
string version1(const string & s1, const string & s2)
{
string temp;//临时变量,只在本函数有效,函数执行完毕,它也不存在了。
//所以这里返回temp的引用不可行。可以返回string
//返回string意味着temp的内容被复制到一个临时的存储单元中
//然后在main方法中,该存储单元的内容被复制到一个名为result的string中
temp = s2 + s1 + s2;
return temp;
}
const string & version2(string & s1, const string & s2) // has side effect
{
s1 = s2 + s1 + s2;
// safe to return reference passed to function
return s1;
}
const string & version3(string & s1, const string & s2) // bad design
{
string temp;//temp引用指向了局部变量。变量销毁,引用指向了空。
temp = s2 + s1 + s2;
// unsafe to return reference to local variable
//warning: reference to local variable 'temp' returned [-Wreturn-local-addr]
return temp;
}
何时使用引用参数
C++ Primer Plus(第6版)中看到一段关于引用参数到总结,原文见8.2.7节。
使用引用参数到主要原因有两个:
(1)程序员能够修改调用函数中的数据对象。
(2)通过传递引用而不是整个数据对象,可以提高程序的运行速度。
当数据对象较大时(如结构和类对象),第二个原因最重要。这些也是使用指针参数的原因。这是有道理的,因为引用参数实际上是基于指针的代码的另一个接口。那么什么时候应该使用引用,什么时候应该使用指针呢?什么时候应该按值传递呢?下面是一些指导原则:
对于使用传递到值而不做修改到函数:
(1)如果数据对象很小,如内置数据类型或小型结构,则按值传递。
(2)如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明为指向const的指针。
(3)如果数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率。这样可以节省复制结构所需要的时间和空间。
(4)如果数据对象是类对象,则使用const引用。类设计的语义常常要求使用引用,这是C++新增这项特性的主要原因。因此,传递类对象参数的标准方式是按引用传递。
对于修改调用函数中数据的函数:
(1)如果数据对象是内置数据类型,则使用指针。如果看到诸如fixit(&x)这样的代码(其中x是int),则很明显,该函数将修改x。
(2)如果数据对象是数组,则只能使用指针。
(3)如果数据对象是结构,则使用引用或指针。
(4)如果数据对象是类对象,则使用引用。
当然,这只是一些指导原则,很可能有充分到理由做出其他的选择。例如,对于基本类型,cin使用引用,因此可以使用cin>>n,而不是cin>>&n。
网友评论