消除临时对象

消除临时对象

在我们的代码中,有些临时对象正在使用而我们并未察觉;
性能优化时,消除临时对象,特别是大的临时对象,对提升性能效果明显;
这里列出常见的临时对象产生的地方:

按值返回

按值返回函数结果,结果就是一个临时对象

string add(string s1,string s2)
{
    string s3;
    s3 = s1+s2;
    return s3;
}

解决方案:

在大多数场景下,这个临时对象可以通过按引用返回来消除;

void add(string s1,string s2,string& retvalue )
{
    retvalue = s1+s2;
}

幸运的是,编译器通常会对按值返回做优化,将其改写为按引用返回;

但编译器做的也是非常保守的工作,仅对匿名返回临时对象做这种按引用传递;

以上函数就不会做,而以下函数,编译器会自动优化为按引用传递:

string add(string s1,string s2)
{
    return s1+s2;
}

注:返回值优化(RVO: return value Optimition):由编译器来完成将值返回转换为引用返回;

按值传递参数

按值传递参数,会有临时对象的分配

string add(string s1,string s2)
{
    string s3;
    s3 = s1+s2;
    return s3;
}

解决方案:

改为按引用传递(如果不希望函数内部修改,加上const修饰符)

string add(const string& s1, const string& s2)
{
    string s3;
    s3 = s1+s2;
    return s3;
}

类型不匹配的隐式转换

赋值操作两边不是同一类型时,如果右边可以作为作为的构造函数的参数做隐式转换,那么就会有临时对象的产生;

比如:

string s1 = "A";

首先会产生一个临时对象string:string("A");

然后赋值给s1: s1 = string("A");

解决方案:

尽量使用相同类型,不用编译器来自动做隐式转换:

比如:

初始化:

string s1("A");    

赋值:

string s1;
s1.assign("A");

连续的对象之间的+操作符

例:

string s3;
s3 = s1+ s2;  

s1+s2的中间结果需要存到一个临时对象中,然后再赋值给s3;

解决方案:

采用+=操作符,一个个的加上需要的对象:

s3 = s1;
s3+= s2;

当然,第一种写法更为优雅,第二种则性能高效;

当此处不是优化关键 路径上的时候,我们还是采用第一种写法就好;

成员对象的初始化

class MyClass
{
    MyClass(){ m_a = "A";}
    private:
        string m_a;
}

成员对象放在构造函数中初始化,那么必然产生一个中间的临时对象;

解决方案:

采用成员初始化列表:

class MyClass
{
    MyClass():m_a("A"){}
    private:
        string m_a;
}

Posted by: 大CC | 06AUG,2015

博客:blog.me115.com [订阅]

Github:大CC

时间: 2024-10-19 14:52:29

消除临时对象的相关文章

临时对象与NRV技术

<More Effective C++>中讲到,在C++中真正的临时对象是看不见的,它们不出现在你的源代码中.建立一个没有命名的非堆(non-heap)对象会产生临时对象,这种未命名的对象通常在两种条件下产生:为了使函数成功调用而进行隐式类型转换和函数返回对象时. 1 size_t countChar(const string& str, char ch); 2 3 int main() 4 { 5 char c; 6 cin >> c >> setw(MAX_

转:C++中临时对象及返回值优化

http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. 通常出现在以下两种情况: (1)为了使函数调用成功而进行隐式类型转换的时候. 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁.如下例: //计算字符ch

[转] C++中临时对象及返回值优化

http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象. 通常出现在以下两种情况: (1)为了使函数调用成功而进行隐式类型转换的时候. 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁.如下例: //计算字符ch

More Effective C++----(19)理解临时对象的来源

Item M19:理解临时对象的来源 当程序员之间进行交谈时,他们经常把仅仅需要一小段时间的变量称为临时变量.例如在下面这段swap(交换)例程里: template<class T> void swap(T& object1, T& object2) { T temp = object1; object1 = object2; object2 = temp; } 通常把temp叫做临时变量.不过就C++而言,temp根本不是临时变量,它只是一个函数的局部对象.(一切事物皆对象

C++标准的规定:非常量的引用不能指向临时对象(转载)

C++标准的规定:非常量的引用不能指向临时对象: 为了防止给常量或临时变量(只有瞬间的生命周期)赋值(易产生bug),只许使用const引用之. 下面的内容转自: http://blog.csdn.net/liuxialong/article/details/6539717 概括一下: 不能把临时对象作为实参传给非const引用. 例如: void conv(string &str) { } int main() { conv("dasd"); // 这里错了,编译器自动生成一

一个函数返回临时对象引起的编译器优化问题

我们都知道,如果在一个函数调用另一个函数,假设是 main 函数调用 fun 函数,这个 fun 函数返回一个临时类类型变量,那么这个时候编译器就会在 main 函数申请一个空间并生成一个临时对象,通过拷贝构造函数将 fun 返回的临时变量的值拷贝到这个临时对象.我们看如下的代码: #include <iostream> #include <cstring> using namespace std; class Matrix { public: explicit Matrix(do

C++临时对象减少的方法

C++临时对象产生的场景: 1. 值传递   2. 函数返回   3. 后置++ 等 减少临时对象产生的方法: 1. 使用引用或指针传递 2. 避免隐式类型转换 3. 使用 += 代替 + string x = a + b; // 这里会产生保存a+b值的临时对象 string x(a); x += b; // 这样就不会产生临时对象 4. 使用前置++代替后置++ 前置++的定义: type operator++(); 后置++的定义: const type operator++(int);

对象追踪、临时对象追踪、绝对坐标与相对坐标

1.对象追踪 快捷键SE 若所画的图形不是在水平或垂直方向上的则按极坐标的方法输入 如下图 临时对象追踪 快捷键  键盘上的ctrl+鼠标右键 与对象追踪差不多只是使用时需要点击起点接下来的步骤与使用对象追踪时的一样 2.绝对坐标 就是以坐标系为原点建立的直角坐标系 输入时按直角坐标系的方法输入(x,y) 如下图 这样输入得到的是一条线段的长度 如果不输入0,0,只输入5,10则就是如下图 相对坐标就是以上一个点为原点建立直角坐标系 输入时在输入的坐标前面加上@然后在输入坐标 当在输入时软件发现

C++临时对象销毁时间

下面这段代码会输出什么? [cpp] view plaincopy const char* p = string("hello temprary string").c_str(); cout << p; 下面这段代码运行之后会怎样? [cpp] view plaincopy #include <vector> class Foo { public: Foo() { _p = new char[32]; } ~Foo() { delete _p; } privat