zoukankan      html  css  js  c++  java
  • C++学习随笔之五:C++函数的新特点

    1.内联函数:是以空间(内存空间)代价换取时间的(程序执行效率),不能使用递归。既可以用于值传递,也可以用于地址传递,而宏不能用于

    值传递。内联函数一般在如下情况下采用:程序中多次调用,而且函数代码执行时间较短时采用。

    2.引用(变量):主要用途是用作函数的形参。

    3.引用与指针的区别:

    (1)引用必须在其声明时就初始化,即必须在创建时就将它初始化,而不像指针那样,可以先声明,后初始化

     #include<iostream>

    using namespace std;

    int main()

    {

    int rat  = 100;

    int & shu = rat;

    cout << "rat = " << rat;

    cout << ", " << "shu = " << shu << endl;

    cout << "rat address: " << &rat ;

    cout <<", " << "shu address: " << &shu <<endl;

    int cat = 50;

    shu = cat;

    cout << "cat = " << cat;

    cout <<", " << "rat = " << cat ;

    cout <<", " << "shu = " << shu <<endl;

    cout <<"cat address: " << &cat;

    cout <<", " << "shu address: " << &shu <<endl;

    cin.get();

    return 0;

    }

    运行上面程序结果如下:

     

    上面结果,显示了,rat的值也变成了50,同时,rat与shu地址相同,而该地址与cat地址不同。因为shu是rat的别名,所以shu=cat语句的与下面语 句等效:rat = cat;也意味着将cat变量的值赋给rat变量。通过上面例子,总之,可以通过初始化声明来设置引用,而但不能通过赋值来设置引用,否则

       会出现意想不到的严重的后果。

    4.引用的一个作用就是用作形参,但注意:用引用做参数时(形参),它很有可能习惯调用函数的值,即实参的值。

    临时变量、引用参数和const:

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

    如果引用参数为const,则在以下两种情况会产生临时变量:

    a.实参的类型不正确,但不是左值。

    b.实参的类型不正确,但可以转换为正确的类型。

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

    非左值包括字面常量和包含多项的表达式。

    示例:

    double refcube(const double & ra)

    {

    return a*a*a;

    }

    double side =3.0;

    double *pd = &side;

    double & rd=side;

    long edge = 5L;

    double lens[4] = {1.0,2.0,3.0,4.0};

    double c1= refcube(side) ; //ra is side;

    double c2=refcube(lens[2]);   //ra is lens[2]

    double c3= refcube(rd);  //ra is rd is side

    double c4 = refcube(*pd);   //ra is *pd is side

    double c5 = refcube(edge); //ra is temporary variable

        double c6 =refcube(7.0); //ra is temporary variable

    double c7 = refcube(side + 10.0); // ra is tempoary variable

    参数side、lens[2]、rd和*pd 都是有名称的、double数据类型的对象,因此可以为其创建引用,而不需要临时变量。但是,edge虽然是变量,类型

    却不正确,double引用不能指向long,还有,参数7.0和side+10.0虽然类型正确,但没有名称,在这种情况下,编译器将生成一个临时匿名变量,

    并让ra指向它。这些临时变量只在函数调用期间存在,此后编译器便可以随便将其删除。

    在没有特殊情况下,一般讲形参引用设为const,应尽可能使用cosnt,原因有如下三点:

    (1)使用const可以避免无意中修改数据的编程错误。

    (2)使用const使函数能够处理const和非const实参,否则将只能接受非const数据

    (3)使用cosnt引用使函数能够正确生成并使用临时变量

    5.引用的第二个作用:用于结构。

    #include<iostream>

    using namespace std;

    struct sysop

    {

    char name[26];

    char quote[64];

    int used;

    };

    const sysop & use(sysop & sysopref)

    {

    cout << sysopref.name <<"says: " << endl;

    cout << sysopref.quote <<endl;

    sysopref.used ++;

    return sysopref;

    }

    int main()

    {

    sysop looper = 

    {

        "caizhiming",

        "宝剑锋从磨砺出,梅花香自苦寒来",

        0 

    };

    use(looper);

    cout <<"Looper: "<<czm.used << " use(s)" <<endl;

    sysop copycat;

    copycat = use(looper); 

    cout <<"Looper: "<<looper.used << " use(s)" <<endl;

    cout <<"Copycat: "<<copycat.used << " use(s)" <<endl;

    cout <<"use(looper): "<<use(looper).used << " use(s)" <<endl;

    cin.get();

    return 0;

    }

    在上面程序代码中,将引用作为返回值。通常,返回机制将返回值复制到临时存储区域中,随后调用程序将访问该区域,然后,返回引用意味着调用程序将直接访问返回值,而不需要拷贝。通常,引用将指向传递函数的引用,因此调用函数实际上是直接访问自己的一个变量。例如上面例子中,sysopref是looper的引用,因此返回值是main函数中的原始looper变量。

    返回引用时应注意:避免返回当函数终止时不再存在的内存单元引用,同样使用指针时也应避免返回指向临时变量的指针!

    6.引用的第三个个作用:用于类对象

    将类对象传递给函数时,C++通常的做法就是使用引用。例如,可以通过引用,让函数将类string、ostream、istream、ofstream和ifstream等类的对象作为参数。如果一个类是从另一个类派生出来的,则基类的引用可以指向派生类的对象。

    7.对于什么时候使用引用,什么时候使用指针,什么时候应按值传递,一般遵循以下原则:

    (1)对于使用传递的值而不作修改的函数:

    a.如果数据对象很小,如内置数据类型或小型结构,则按值传递。

    b.如果数据对象是数组,则使用指针,因为这是唯一的选择,并且将指针声明为指向const的指针。

    c.如果数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率。这样可以节省复制结构的空间和时间。

    d.如果数据对象是类对象,则使用const引用。类设计的语义常常要求使用引用,这是C++新增引用的主要原因,因此,传递类对象参数的标准方式是

    按引用传递。

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

    a.如果数据对象是内置数据类型,则使用指针。如果看到fixit(&x)这样的代码(其中x是int类型),改函数将修改x。

    b.如果数据对象是数组,则使用指针。

    c.如果数据对象是结构,则使用引用或指针。

    d.如果数据对象是类对象,则使用引用。

    引用的引入只要适用于结构和类对象的。

    8.函数重载:函数重载的关键是参数列表——也称为函数特征标。函数重载必须是特征标不同,返回类型可以不相同。函数名相同,只需要特征标(参数列表)不同,就是函数多态(或函数重载)。函数模板自动完成重载函数的过程。

    9.函数模板:这里要注意的是 template<class T> 不是一个独立的语句,它必须和方法定义声明或类声明是一体的,虽然有时分两行来写。

    代码示例:

    #include<iostream>

    using namespace std;

    template<class T>

    void Swap(T &a,T &b);

    template <class T>

    void Swap(T &a,T &b)

    {

    T temp;

    temp = a;

    a = b;

    b = temp;

    }

    int main()

    {

    int i=10;

    int j=20;

    cout << i << "," << j <<endl;

    Swap(i,j);

    cout << i << "," << j <<endl;

    double m = 12.34;

    double n =20.57;

    cout << m << "," << n <<endl;

    Swap(m,n);

    cout << m << "," << n <<endl;

    cin.get();

    return 0;

    }

    10.默认参数:

    如果第N个参数默认的话,第N+1 N+2 …… 个都应该是默认参数,所以默认参数应该放在参数列表的最“后”面。也即是说,如果要为某个参数设置为默认值,则必须为后面的所有参数提供默认值。

  • 相关阅读:
    第10组Beta冲刺(4/4)
    第10组Alpha冲刺(4/4)
    第08组 Beta版本演示
    第08组 Beta冲刺(3/4)
    第08组 Beta冲刺(4/4)
    第08组 Beta冲刺(1/4)
    第08组 Beta冲刺(2/4)
    第08组 Alpha事后诸葛亮
    第08组 Alpha冲刺(4/4)
    第08组 Alpha冲刺(3/4)
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/2964801.html
Copyright © 2011-2022 走看看