Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在c++;影响效率?_C++ - Fatal编程技术网

C++ 如何在c++;影响效率?

C++ 如何在c++;影响效率?,c++,C++,我读过一篇关于CodeProject的文章 我不明白为什么第二个statment不创建临时对象?编译器是如何工作的? 在C++中有一个规则,它允许编译器直接调用临时的临时变量。 无论如何,使用它的回旋余地,编译器可以在不使用此规则的情况下优化示例,这具有相同的效果 12.8复制和移动类别对象§32 当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使该对象的复制/移动构造函数和/或析构函数有副作用。在这种情况下, 该实现将省略的复制/移动操作的源和目标视为两个不同的操作 指代同一对象的方

我读过一篇关于CodeProject的文章


我不明白为什么第二个statment不创建临时对象?编译器是如何工作的?

在C++中有一个规则,它允许编译器直接调用临时的临时变量。 无论如何,使用它的回旋余地,编译器可以在不使用此规则的情况下优化示例,这具有相同的效果

12.8复制和移动类别对象§32 当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使该对象的复制/移动构造函数和/或析构函数有副作用。在这种情况下, 该实现将省略的复制/移动操作的源和目标视为两个不同的操作 指代同一对象的方式,并且该对象的销毁发生在时间较晚的时候 如果没有优化,这两个对象将被销毁。123这省略了复制/移动 在以下情况下允许进行称为复制省略的操作 消除多个副本):
-在具有类返回类型的函数中的return语句中,当表达式是 具有相同参数的非易失性自动对象(函数或catch子句参数除外) 类型作为函数返回类型,可以通过构造 自动对象直接输入函数的返回值
-在抛出表达式中,当操作数是非易失性自动对象(非易失性自动对象)的名称时 函数或catch子句参数),其作用域不超出最内层 封闭try块(如果有),从操作数到异常的复制/移动操作 通过将自动对象直接构造到异常对象中,可以省略对象(15.1)
-复制/移动未绑定到引用(12.2)的临时类对象时 对于具有相同cv类型的类对象,可以通过 将临时对象直接构造到省略的复制/移动的目标中
-当异常处理程序(第15条)的异常声明声明相同类型的对象时 (cv鉴定除外)作为例外对象(15.1),可以省略复制/移动操作 通过将异常声明视为异常对象的别名,如果程序的含义 将保持不变,除了为声明的对象执行构造函数和析构函数 异常声明


在您提供的链接的第一个示例中,赋值运算符被称为:

Complex x, y, z;
x=y+z;
Complex y,z;
Complex x=y+z;
在您提供的链接的第二个示例中,构造函数被称为:

Complex x, y, z;
x=y+z;
Complex y,z;
Complex x=y+z;
但在这两种情况下,都会创建一个临时对象(包含
x+y
)的值

因此,我严重怀疑这种联系的正确性

我很乐意阅读对你的问题的任何回答,这些回答可以解释其他问题


我们可以避免的临时对象通常是通过值而不是引用传递给函数或从函数返回的对象

例如,在下面的
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;
    ...
}
为了消除这两个临时对象,只需通过引用传递和返回:

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

请注意,通过引用传递参数在成员函数和全局函数中都是可行的,但是通过引用返回参数仅在成员函数中是可行的(除非从全局函数返回全局变量,但在大多数情况下这是毫无意义的).

由于存在赋值,从
x
到结果
y+x
复合体
可能有一个复制赋值操作符。因此,值被复制。您可能正在这里查看返回值优化(RVO)。在您提供的链接的第一个示例中,调用赋值运算符。在您提供的链接的第二个示例中,调用了构造函数。但我相信在这两种情况下都会创建一个临时对象(包含
x+y
)的值。因此,我严重怀疑这种联系的正确性。我很乐意在这里读到你问题的答案。我们可以避免的临时对象通常是通过值传递给函数或从函数返回的对象,而不是通过引用。这篇文章是错误的,结果
y+z
是右值。@barakmanos AFAIK,编译器可以优化复制(即复制构造函数调用)。即使复制构造函数中存在可能影响运行时行为的代码,它也会这样做。基本上,如果您想要对象的副本,请不要依赖编译器来制作副本。你自己打电话吧。谢谢你的帮助。我也怀疑这个链接的正确性,但我不能确认它的正确性。