【问题标题】:c++: Is object pointed to by a "pointer to const" considered unchanging or just unmodifiable?c ++:“指向const的指针”指向的对象是否被认为是不变的或只是不可修改的?
【发布时间】:2014-11-28 20:49:27
【问题描述】:

在以下情况下,“指向 const bool 的指针”参数pbAbort 是有意义的,因为工作函数不会修改 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 限定的访问路径不能用于修改对象,即使引用的对象是非常量对象并且可以通过其他访问路径进行修改。

很遗憾,这句话并不能完全回答我的问题。

【问题讨论】:

  • bool const *const pbAbort 应该是什么意思?
  • 为什么你需要一个指向 bool 的指针而不是一个普通的 bool?如果指针和bool 都是const 则不可能是您需要在某处修改原始值。
  • 您可以通过使用可以修改的简单参考来避免很多这种混乱。
  • @caps:实际上,它可以。例如,另一个参数 (data) 可能是一个对象,该对象具有一个在此函数中某处被修改的 bool 成员。 pbAbort 可能是指向该成员的指针。
  • @BenjaminLindley 好点。我还从他的函数中注意到他可能正在处理线程,在这种情况下另一个线程可能会更改值。

标签: c++ pointers constants compiler-optimization


【解决方案1】:

要回答您的问题,如果编译器不相信变量正在被修改,它可以优化多次读取,无论对象是否为 const。考虑到读取线程中的代码路径未写入变量,这很可能发生在您的代码中。

这里需要注意的是,您的程序实际上包含未定义的行为;默认情况下,跨线程读取写入变量不是原子的。要安全地执行此操作,您需要atomic&lt;bool&gt;。另见this question。另外,不要使用volatile。它将解决您的重新排序问题,但对 volatile 变量的访问仍然不是原子的(因此仍然是 UB)。

标准声明没有回答您的问题的原因是它谈论的是一个线程中的读取和写入。

【讨论】:

    【解决方案2】:

    如果编译器无法证明指向的对象实际上是 const,则标准中的任何内容都不允许它假设它是 - 所以它无法优化读取。

    (如果它可以看到更多代码 - 例如,如果函数是内联的或正在使用整个程序优化 - 那么它可能能够在知道没有写入时跳过读取。)

    【讨论】:

      猜你喜欢
      • 2014-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 1970-01-01
      • 2011-01-14
      • 2020-10-02
      相关资源
      最近更新 更多