zoukankan      html  css  js  c++  java
  • c/c++:efficient c++,临时对象

    说个题外话

    #include <iostream>
    using namespace std;
    
    class A
    {
    public:
        char a;
        char b;
        char c;
    public:
        A(char aa, char bb=97, char cc=97):a(aa),b(bb),c(cc){}
    };
    
    int main()
    {
        A e=98;
        cout<<e.a<<e.b<<e.c<<endl;
        return 0;
    }

    对于 下面的 A e= 98;  是能够匹配到A的构造函数的,aa 需不需要默认值都可以,这样的声明会将 98 赋予第一个 参数,即aa 。

    主要内容:

    class Rational
    {
        friend Rational operator +(const Rational &,const Rational &);
    public:
        Rational(int a=0,int b=1):m(a),n(b){}
    private:
        int m;
        int n;
    };

    对于对象定义:

    Rational r1(100);
    Rational r2 = Rational(100);
    Rational r3= 100;

    只有第一个r1 是不会创建临时变量的,另外两个都会。不过编译器优化了,所以3者效率一样。

    对于类型不匹配:

    Rational r;
    r=100;

    这样第二句会寻找Ratiaonal  的构造函数(如我上面写的那个题外话),然后再调用拷贝函数实现。

    想禁止这用转换,可以再构造函数(对于其他什么函数都适用)前面加 explicit

    class Rational
    {
    public:
        explicit Rational(int  a=0, int b=1):m(a),n(b){}
    };

    有时候调用函数时会产生临时变量的,如

    void g(const string &s){}
    
    g("message");

    下面的调用函数中传递的是指针。

    再按例子 Complex类

    complex a,b;
    for(int i=0;i<100;i++)
    {
        a= i*b +1.0;
    }
    
    complex a,b;
    complex one(1,0);
    for(int i=0;i<100;i++)
    {
        a= i*b +one;
    }

    上面部分中的1.0 需要不断的创建于销毁。

    按值传递

    一般的调用:

    T t;
    g(t);

    编译器将需要创建T 类型的临时对象,并且用t 作为输入参数调用拷贝构造函数创建这个变量,然后以这个变量作为实参传递给个g(),然后返回时调用析构函数释放临时变量。

    按值返回:

    调用函数会创建变量保存返回值,如果有赋值语句就调用赋值函数,最后是释放临时变量。 

    通过上一章可以消除在被调用函数中的临时变量 (RVO)。

    至于消除当前函数的临时变量。就要考虑。

    对于语句 s3=s1 +s2. 源函数会产生一个临时变量保存 s1+s2 的值。为什么会产生呢? 

    这是两个操作 ,+  = ,对于s1+s2 部分没有权利修改s3 的值。(这是 = 的是功能)。

    如果s3 有旧值时,不能将s3 作为这一临时变量,但如果s3 是新声明的,便能直接作为该变量,这样就省了一个临时变量。

    写法:

    //有临时变量
    string s1= "Hello ";
    string s2= "World ";
    string s3;
    s3=s1+s2;
    //无临时变量
    string s1= "Hello ";
    string s2= "World ";
    string s3=s1+s2;

    至于在s3 有旧值的情况下,可以这样来避免创建临时变量。

    //有临时变量
    string s1,s2,s3,s4;
    s1=s2+s3+s4;
    //无临时变量
    s1=s2;
    s1+=s3;
    s1+=s4;

    要点:

    1.临时对象会以构造函数和析构函数的形式降低一半的性能。

    2.将构造函数声明为 explicit,可以阻止编译器幕后使用类型转换。

    3.编译器常常创建临时对象来解决类型不匹配问题。通过重载可以避免这种情况。

    4.如果肯尼个,尽量避免使用对象拷贝(应该指函数调用的时候),按引用传递和返回对象。

    5.在<op>可能是“+-*/”的地方,使用 <op>=运算符可以消除临时对象。

  • 相关阅读:
    面向对象静态语言的模型
    语言的静态分析技术
    面向对象的核心元素与机制
    Lua 笔记
    Linux配置系统
    Linux文件类型
    Wijmo 日历插件
    窗外大雨,心里小雨
    一次胆战心惊的服务器经历
    一次胆战心惊的服务器经历
  • 原文地址:https://www.cnblogs.com/Azhu/p/2591555.html
Copyright © 2011-2022 走看看