美文网首页
Effective c++ 学习笔记(item20)

Effective c++ 学习笔记(item20)

作者: 懒生活 | 来源:发表于2022-08-30 22:32 被阅读0次

    # 尽量选择pass-by-reference-to-const 而不是使用pass-by-value

    c++在默认情况下会大量的使用pass by value,这主要是因为对c的继承。对于函数的入参和返回,c++默认情况下都是拷贝构造一个临时对象,然后在函数里面使用。对于返回值也是,要先拷贝构造出一个临时对象,然后赋值给调用外层。

    ## 选择pass-by-reference-to-const好处之一避免了毫无意义的拷贝构造

    看下面的调用关系

    ```

    Student plato;

    validateStudent(plato);

    ```

    在这个调用关系下,如果定义成bool validateStudent(Studeng s); 那么在调用这个函数的时候,会发生大量没有任何意义的拷贝构造。首先需要通过plato拷贝构造临时对象,但构造该临时对象前,需要先拷贝构造plato内部的成员对象。为什么要拷贝构造的,为什么不能直接用plato对象呢。

    这种函数调用关系的入参可以全部使用引用才对。如果需要在函数里面修改plato就用第一种定义,如果不需要就用第二种定义

    ```

    bool validateStudent(Student&s);

    bool validateStudent(const Student& s);

    ```

    ## 选择pass-by-reference-to-const好处之二避免了多态应用引发的slicing problem

    ```

    class BaseClass

    {

    public:

        virtual void printName() const{cout<<""this is base class" <<endl;}

    };

    class AClass : public BaseClass

    {

    void printName() const { cout <<"this is a AClass" << endl;}

    };

    void printClassName(const BaseClass& abc){abc.printName();};

    //void printClassName(BaseClass abc)

    //{ abc.printName();}

    int main()

    {

    AClass abc;

    printClassName(abc);

    }

    ```

    如果使用注释掉的定义void printClassName(BaseClass abc); 那么在调用printClassName(abc)的时候,编译器首先通过拷贝构造创建一个临时BaseClass对象,并从abc中只拷贝属于BaseClass对象的成员和相关函数映射表。这样在函数内部,abc就是纯粹的BaseClass类型了。这和你希望打印出子类型的名字的期望相悖。

    相关文章

      网友评论

          本文标题:Effective c++ 学习笔记(item20)

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