在以下情况中,“指向const bool的参数”参数pbAbort
是有意义的,因为worker函数不会修改bool对象。但是,我担心编译器可能会优化对bool值的多次检查,除非我使用普通的“指向bool的指针”。 bool是一个可以由经理线程设置的标志。
void runWorkManager(DataSet& data)
{
bool bAbort = false;
callWorkerFuncFromNewThread(data, &bAbort);
while(!(data.isWorkCompleted || data.isWorkAborted))
{
updateGuiWithProgress(data.progress);
if(userWantsToAbort())
bAbort = true;
}
}
void workerFunc(DataSet& data, bool const *const pbAbort)
{
data.doPreWork();
if(*pbAbort) //Check #1
{
data.isWorkAborted = true;
return;
}
for(int i = 0; i < 100; ++i)
{
data.doWorkN(i);
if(*pbAbort) //Check #2
{
data.isWorkAborted = true;
return;
}
}
data.isWorkCompleted = true;
}
如果假设*pbAbort
永远不会改变,那么编译器可以删除Check#2块。
7.1.6.1.3中的c ++ 11标准声明:
对cv限定类型的指针或引用实际上不需要指向或引用cv限定的对象,但它被视为具有;即使引用的对象是非const对象并且可以通过其他一些访问路径进行修改,也不能使用const限定的访问路径来修改对象。
不幸的是,这句话并没有完全回答我的问题。
答案 0 :(得分:2)
要回答您的问题,如果编译器不相信该变量正在被修改,它可以优化掉多个读取,无论该对象是否为const。考虑到读取线程中的代码路径没有写入变量,这很可能发生在您的代码中。
这里需要注意的是,您的程序实际上包含未定义的行为;默认情况下,跨线程读取写入变量不是原子的。要安全地执行此操作,您需要atomic<bool>
。另见this question。另外,请勿使用volatile
。它将修复您的重新排序问题,但访问volatile
变量仍然不是原子的(因此仍然是UB)。
标准声明没有回答你的问题的原因是它在一个线程内讨论读写。
答案 1 :(得分:1)
如果编译器无法证明指向的对象实际上是const
,则标准中没有任何内容允许它假设它是 - 因此它无法优化读取。
(如果它可以看到更多的代码 - 例如,如果函数是内联的或整个程序优化正在使用 - 那么当它可以告诉没有写入时它可能能够跳过读取。)