zoukankan      html  css  js  c++  java
  • 传参时,使用引用替换变量

    第一个原因。。。

    C++默认使用变量的方式传递对象。假如没有另外指定,函数的参数都是以实参的副本为初值,而函数的返回值也是一个复件。这些复件由对象的copy构造函数产出,这会让值传递成为昂贵的操作。来一个简单的例子

    class Person
    {
    public:
        Person();
        virtual ~Person();
    private:
        std::string name;
        std::string address;
    };
    class Student:public Person
    {
    public:
        Student();
        ~Student();
    private:
        std::string schoolName;
        std::string schoolAddress;
    };
    bool validateStudent(Student s);          //以值的方式接受学生
    Student plato;                            //柏拉图
    bool platoIsOK = validateStudent(plato);  //调用函数  
    

    简单地看,Student的复制构造函数在传入参数的时候会被调用,产生plato的副本初始化s,同样,返回的时候将s销毁,调用一次析构函数。也就是参数的传递成本是“一次Student的复制构造函数与一次student的析构函数”。但是,让我们解剖一下Student。

    一个Student中有4个string对象,2个继承自Person,2个Student自己定义。而每个string也是一个实例,意味着每个Student初始化的时候string会被初始化时,就会初始化4个string,一个Person,每个Student销毁时,就会销毁四个string,一个Person,所以,真正的调用这个函数的时候,参数传递的成本是“六次构造函数与六次析构函数”!!!

    想到这些,顿时间十分堪忧我们程序的性能。解决的方法就是,使用引用代替普通的值传递。当然,假如需要保护形参,我们还可以加上const限制。

    bool validateStudent(const Student& s);

    因为引用实际上是通过指针来实现的。引用一句话,"变量可以看成变量的别名”,也就是,使用引用是不会创建新的实例的。所以使用这种传递方式,效率高了很多,没有任何构造函数与析构函数被调用,因为没有创建任何新的实例。

    第二个原因。。。
    当然,使用引用的好处不仅仅是这些。使用引用的方式传递参数,还可以避免对象切割的问题。当派生类的对象传递给基类的对象时,调用的是基类的构造函数,派生类的那些特性将会被全部切割掉。试想一下有如下代码。

    class Window
    {
    pubic:
        virtual void Display()const;    //显示窗口的名字  
    };
    class WindowWithScrollBars:public Window
    {
    public:
        virtual void Display()const;    //显示窗口和内容
    };
    

    当我们用一个WindowWithScrollBars类型的对象初始化一个Window类型的对象后,在Window对象后调用Display,一切不值得惊讶又让人懊恼,我想显示一个窗口和内容但实际上它只给了我一个窗口的名字。学习了虚函数之后,我们知道这可以通过指针来解决,同样的,使用引用也能解决这个问题。

    第三个原因。。。

    编译器对内置类型与用户自定义类型的态度不太一致。比如,有些编译器会将一个double放入缓冲器中,但是却拒绝将一个只有double的class放入缓冲器中。而当我们使用引用的时候,引用是指针实现的,编译器当然会将指针放入缓冲器中。

    第四个原因。。。

    你认为你的class很小,直接使用变量传递与使用引用传递没有区别。但是,没有人能够保证class一直很小。就比如,class里面只有一个string,看起来真的很小,但不同的库的string大小相差非常大,当你认为class很小的时候,它实际已经无限膨胀了。再比如,假如没有使用引用,每次向class中增加内容的时候,你得小心翼翼增加的内容是否对你的性能会造成很大的影响。而假如你不希望有这种心理阴影,还是使用引用吧。

    但是话说回来,又不是要求我们每时每刻都要使用引用来代替变量,比如,当我们使用STL库的时候。STL库习惯被设计成以变量的方式传递。比如传递其迭代器。所以,当我们使用STL库的时候,我们直接使用变量传递参数会优于引用。

    总结一下

    1. 使用引用传递参数会比变量更高效
    2. 使用引用传递参数可以避免对象切割的问题
    3. 不是所有的时候都使用引用比时候变量好,比如当使用STL库或者函数对象的时候。
  • 相关阅读:
    C#学习
    1.计算机的硬件
    C++ bitset——高端压位卡常题必备STL
    Aragorn's Story
    Sql Server DTS使用
    Django的SQL注意事项(以及时间戳转换日期格式)
    HTML中复选框的使用方法
    Http常见状态码
    scrapy yield 回调函数不执行解决方案
    jsonp跨域请求
  • 原文地址:https://www.cnblogs.com/suimeng/p/4885491.html
Copyright © 2011-2022 走看看