C++ 针对用作“文件”的临时对象的编译器优化;康斯特&引用;循环中的函数参数?

C++ 针对用作“文件”的临时对象的编译器优化;康斯特&引用;循环中的函数参数?,c++,c++11,visual-c++,optimization,C++,C++11,Visual C++,Optimization,下面我有一个永久线程循环,调用std::this\u thread::sleep\u以延迟10毫秒。持续时间是一个临时对象std::chrono::毫秒(10)。在一些示例代码之后,延迟调用看起来“正常”和“典型”。然而,再仔细看一看,很明显,在每个周期中,temp duration对象都会创建和销毁一次 // Loop A. for (;;) {     std::this_thread::sleep_for(std::chrono::milliseconds(10));     // Do 

下面我有一个永久线程循环,调用
std::this\u thread::sleep\u以延迟10毫秒。持续时间是一个临时对象
std::chrono::毫秒(10)
。在一些示例代码之后,延迟调用看起来“正常”和“典型”。然而,再仔细看一看,很明显,在每个周期中,temp duration对象都会创建和销毁一次

// Loop A.
for (;;)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    // Do something.
}
现在,如果duration对象是在循环之外创建的(作为常量),那么对于所有循环,它将只构造一次。请参阅下面的代码

// Loop B.
const auto t = std::chrono::milliseconds(10);
for (;;)
{
    std::this_thread::sleep_for(t);
    // Do something.
}

<强>问题:由于STD::THEXTY::使用“const &”作为其参数类型的SyeLip,任何C++编译器都会将循环A内的临时持续时间对象优化成循环B?<强> > /p>。 我在下面尝试了一个简单的测试程序。结果表明,VC++2013没有优化“const&”temp对象

#include <iostream>
#include <thread>

using namespace std;

class A {
public:
    A() { cout << "Ctor.\n"; }
    void ReadOnly() const {}  // Read-only method.
};

static void Foo(const A & a)
{
    a.ReadOnly();
}

int main()
{
    cout << "Temp object:\n";
    for (int i = 0; i < 3; ++i)
    {
        Foo(A());
    }

    cout << "Optimized:\n";
    const auto ca = A();
    for (int i = 0; i < 3; ++i)
    {
        Foo(ca);
    }
}
/* VC2013 Output:
Temp object:
Ctor.
Ctor.
Ctor.
Optimized:
Ctor.
*/
#包括
#包括
使用名称空间std;
甲级{
公众:

MSVC和其他现代编译器完全能够优化循环中的临时对象

问题在于,在构造函数中,你有一个强的副作用<强>。按照C++标准,编译器不允许优化你的临时对象的创建/销毁,因为它不再产生相同的可观察的效果(即打印3次)。 如果不再

cout
something,情况就完全不同了。当然,您必须查看生成的汇编代码来验证优化

例如:

class A {
public:
    static int k;    
    A() { k++;  }   
    void ReadOnly() const {}  // Read-only method.
};
int A::k = 0; 

// Foo unchanged

int main()
{
    for(int i = 0; i < 3; ++i)
        Foo(A());  // k++ is a side effect, but not yet observable 
    volatile int x = A::k;     // volatile can't be optimized away

    const auto ca = A();
    for(int i = 0; i < 3; ++i)
        Foo(ca);
    x = A::k;     // volatile can't be optimized away
    cout << x << endl; 
}
A类{
公众:
静态int k;
A(){k++;}
void ReadOnly()常量{}//只读方法。
};
int A::k=0;
//福不变
int main()
{
对于(int i=0;i<3;++i)
Foo(A());//k++是一个副作用,但尚未观察到
volatile int x=A::k;//volatile无法优化
常数自动ca=A();
对于(int i=0;i<3;++i)
Foo(ca);
x=A::k;//volatile无法优化
cout假设编译器“理解”构造函数所做的事情(换句话说,在翻译单元中有可用的构造函数源代码-即,源文件或一个头文件,包含该构造函数的定义),则编译器应删除对构造函数的无副作用的多余调用

由于打印某些内容是
a
构造函数的一个非常明确的副作用,编译器显然无法对此进行优化。因此,编译器做的正是“正确的”例如,如果您有一个锁持有构造函数,然后释放析构函数中的锁,并且编译器决定优化您的:

for(...)
{
   LockWrapper lock_it(theLock);
   ... some code here 
}
到循环之外,因为尽管获取和释放锁的开销较低,但代码的语义会发生变化,并且锁的持续时间可能会更长,这将对使用相同锁的其他代码产生影响,例如在不同的线程中。

for(...)
{
   LockWrapper lock_it(theLock);
   ... some code here 
}