Gar*_*and 3 c++ optimization visual-c++ c++11
我有一个永远的线程循环调用std::this_thread::sleep_for延迟10毫秒.持续时间是临时对象std::chrono::milliseconds(10).一些示例代码后,延迟调用似乎是"正常"和"典型".然而,仔细观察,很明显,在每个循环中,临时持续时间对象被创建并销毁一次.
// Loop A.
for (;;)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// Do something.
}
Run Code Online (Sandbox Code Playgroud)
现在,如果在循环外创建持续时间对象(作为常量对象),则它将仅针对所有循环构造一次.请参阅下面的代码.
// Loop B.
const auto t = std::chrono::milliseconds(10);
for (;;)
{
std::this_thread::sleep_for(t);
// Do something.
}
Run Code Online (Sandbox Code Playgroud)
问题:由于std :: this_thread :: sleep_for使用"const&"作为其参数类型,所以任何C++编译器都会将Loop A中的临时持续时间对象优化为Loop B吗?
我在下面尝试了一个简单的测试程序 结果表明VC++ 2013没有优化"const&"临时对象.
#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.
*/
Run Code Online (Sandbox Code Playgroud)
Chr*_*phe 12
MSVC和其他现代编译器完全能够优化循环中的临时对象.
您的示例中的问题是您在构造函数中有副作用.根据C++标准,编译器不允许优化临时对象的创建/销毁,因为它不再产生相同的可观察效果(即打印3次).
如果你不再cout是某种东西,那么情况就完全不同了.当然,您必须查看为验证优化而生成的汇编代码.
例:
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;
}
Run Code Online (Sandbox Code Playgroud)
优化器完全注意到它是相同的静态变量,它会增加,而不是在其他地方使用.所以这里生成的汇编程序代码(提取):
mov eax, DWORD PTR ?k@A@@2HA ; A::k <=== load K
add eax, 3 <=== add 3 to it (NO LOOP !!!)
mov DWORD PTR ?k@A@@2HA, eax ; A::k <=== store k
mov DWORD PTR _x$[ebp], eax <=== store a copy in x
inc eax <=== increment k
<=== (no loop since function doesn't perform anything)
mov DWORD PTR ?k@A@@2HA, eax ; A::k <=== store it
mov DWORD PTR _x$[ebp], eax <=== copy it to x
Run Code Online (Sandbox Code Playgroud)
当然,您需要在发布模式下进行编译.
如您所见,编译器非常聪明.因此,让他完成自己的工作,专注于您的代码设计,并牢记: 过早优化是所有邪恶的根源 ;-)
| 归档时间: |
|
| 查看次数: |
733 次 |
| 最近记录: |