简体   繁体   English

c ++中的临时对象如何影响效率?

[英]How the temporary objects in c++ affect the efficiency?

I have read an article on CodeProject http://www.codeproject.com/Tips/103648/C-Tip-How-to-eliminate-Temporary-Objects . 我读过一篇关于CodeProject的文章http://www.codeproject.com/Tips/103648/C-Tip-How-to-eliminate-Temporary-Objects

Complex y,z;
Complex x=y+z; /* initialization instead of assignment */

I confused that why the second statment does not create a temporary object? 我混淆了为什么第二个语句没有创建临时对象? how does the compiler works? 编译器如何工作?

There is a rule in C++, which allows the compiler to ellide temporaries, if they are directly used for initialising. C ++中有一条规则,如果它们直接用于初始化,它允许编译器同步临时数据。
Anyway, using its leeway, the compiler could optimize the example without this rule anyway, which has the same effect. 无论如何,使用它的余地,编译器可以在没有这个规则的情况下优化示例,这具有相同的效果。

12.8 Copying and moving class objects §32 12.8复制和移动类对象§32

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects. 当满足某些条件时,允许实现省略类对象的复制/移动构造,即使该对象的复制/移动构造函数和/或析构函数具有副作用。 In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization.123 This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies): 在这种情况下,实现将省略的复制/移动操作的源和目标视为仅仅两种不同的引用同一对象的方式,并且该对象的销毁发生在两个对象的后期时间。在没有优化的情况下销毁.123在下列情况下允许复制/移动操作(称为复制省略)的这种省略(可以合并以消除多个副本):
— in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cvunqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function's return value - 在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cvunqualified类型的非易失性自动对象(函数或catch子句参数除外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作
— in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object - 在throw-expression中,当操作数是非易失性自动对象的名称(函数或catch子句参数除外),其范围不会超出最内层封闭try-block的末尾(如果有的话)一),通过将自动对象直接构造到异常对象中,可以省略从操作数到异常对象(15.1)的复制/移动操作
— when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move - 当一个未绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-nonqualified类型的类对象时,可以通过将临时对象直接构造到该对象中来省略复制/移动操作。省略的复制/移动的目标
— when the exception-declaration of an exception handler (Clause 15) declares an object of the same type (except for cv-qualification) as the exception object (15.1), the copy/move operation can be omitted by treating the exception-declaration as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the exception-declaration. - 当异常处理程序的异常声明(第15条)声明一个相同类型的对象(cv-qualification除外)作为异常对象(15.1)时,可以通过处理异常声明来省略复制/移动操作如果除了为exception-declaration声明的对象执行构造函数和析构函数之外,程序的含义将保持不变,则作为异常对象的别名。

In the first example in the link that you provide, the assignment operator is called: 在您提供的链接的第一个示例中,调用赋值运算符:

Complex x, y, z;
x=y+z;

In the second example in the link that you provide, the constructor is called: 在您提供的链接的第二个示例中,将调用构造函数:

Complex y,z;
Complex x=y+z;

But in both cases, a temporary object (containing the value of x+y ) is created. 但在这两种情况下,都会创建一个临时对象(包含x+y的值)。

So I seriously doubt the correctness of this link. 所以我严重怀疑这个链接的正确性。

I would be happy to read any answer to your question that explains otherwise... 我很乐意阅读你的问题的任何答案,否则解释......


Temporary objects that we can avoid are usually the ones passed to a function or returned from a function by value instead of by reference. 我们可以避免的临时对象通常是传递给函数或通过值而不是通过引用从函数返回的对象。

For example, in Complex::operator+= below, one temporary object is created on the stack when the function is called, and another temporary object is created on the stack when the function returns: 例如,在下面的Complex::operator+=中,在调用函数时在堆栈上创建一个临时对象,并在函数返回时在堆栈上创建另一个临时对象:

Complex Complex::operator+=(Complex num)
{
    this->real += num.real;
    this->imag += num.imag;
    return *this;
}

void func()
{
    Complex a(1,2);
    Complex b(3,4);
    a += b;
    ...
}

In order to eliminate both temporary objects, you can simply pass and return by reference: 为了消除这两个临时对象,您可以简单地通过引用传递和返回:

Complex& Complex::operator+=(Complex& num)
{
    ...
}

Please note that passing an argument by reference is feasible in member functions as well as in global functions, but returning an argument by reference is feasible only in member functions (unless you return a global variable from a global function, but that is rather pointless in most cases). 请注意, 通过引用传递参数在成员函数和全局函数中是可行的,但是通过引用返回参数仅在成员函数中是可行的(除非您从全局函数返回全局变量,但这在在大多数情况下)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM