美文网首页
03_C++笔记_函数二

03_C++笔记_函数二

作者: 平头哥2 | 来源:发表于2019-06-03 16:23 被阅读0次

函数指针:

#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。

相关文章

  • 03_C++笔记_函数二

    函数指针: 内联函数: 引用 将引用变量作为参数(交换两个数的实现): 引用的属性和特别之处: 引用用于结构: 将...

  • 向量值函数笔记: L^p空间

    这是向量值函数(B值函数)系列笔记的第二篇. 为方便阅读, 这里放出目录:(1)向量值函数笔记: Bochner积...

  • 2019-02-25

    @[TOC](2.25机器学习数学基础笔记之二) 1. 凸函数的判定(开口往上凸函数 开口往下凹函数) ![在这里...

  • JS笔记(二)函数

    什么是函数呢?就是可以装任意多条代码,形成一个代码块,那么这个代码块有什么作用呢,当然是为了重复利用咯 怎么判断一...

  • Dart笔记(二)函数

    方法也是对象,Function返回值类型、参数类型可省略箭头语法: = > expr 也就是{return exp...

  • Python学习笔记-Day06(二)

    Python学习笔记 Day_06-函数(二) 上节学习了函数的一些基本知识和用法。这一节继续学习函数参数的传递方...

  • 1.5.1 Python函数初识

    点击跳转笔记总目录 一、为什么要使用函数? 1,避免代码重用2,提高代码的可读性 二、函数的定义与调用 1,函数定...

  • c++第二周笔记

    C++ 第二周笔记 本周的内容比较多,主要介绍了三个重要函数: 拷贝构造、拷贝赋值、析构函数。 1.拷贝构造函数。...

  • [刷题记录] 剑指 Offer 27. 二叉树的镜像

    2021.11.29算法笔记 剑指 Offer 27. 二叉树的镜像 请完成一个函数,输入一个二叉树,该函数输出它...

  • 初三期末备考第5天

    一、视频讲解 趣味动漫小视频教你:二次函数 二、笔记推送 三、作业练习 昨日答案 今日作业

网友评论

      本文标题:03_C++笔记_函数二

      本文链接:https://www.haomeiwen.com/subject/yvocxctx.html