c++:"pointer to const"指向的对象是否被认为是不变的还是不可修改的?
c++: Is object pointed to by a "pointer to const" considered unchanging or just unmodifiable?
在以下情况下,"指向const bool的指针"参数pbAbort
有意义,因为worker函数不会修改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
永远不会更改,则编译器可以删除检查 #2 块。
7.1.6.1.3 的 c++ 11 标准指出:
指向 cv 限定类型的指针或引用实际上不需要指向或引用 cv 限定的对象,但它被视为这样做;即使引用的对象是非 const 对象,也不能使用常量限定的访问路径来修改对象,并且可以通过其他访问路径进行修改。
不幸的是,这句话并没有完全回答我的问题。
为了回答你的问题,如果编译器不相信变量正在被修改,它可以优化多次读取,无论对象是否是常量。考虑到读取线程中的代码路径不会写入变量,这很可能发生在您的代码中。
这里需要注意的是,你的程序实际上包含未定义的行为;默认情况下,跨线程读取写入变量不是原子的。要安全地执行此操作,您需要一个 atomic<bool>
.另请参阅此问题。另外,不要使用 volatile
.它将解决您的重新排序问题,但对volatile
变量的访问仍然不是原子的(因此仍然是 UB)。
标准声明没有回答您的问题的原因是它谈论的是在一个线程中的读取和写入。
如果编译器不能证明指向的对象实际上是const
的,那么标准中的任何内容都不允许它假设它是 - 所以它不能优化读取。
(如果它可以看到更多的代码 - 例如,如果函数是内联的或整个程序优化正在使用中 - 那么当它可以判断没有写入时,它可能会跳过读取。
相关文章:
- 为什么rand()的使用被认为是不好的
- 为什么 std::shared_ptr 被认为是"heavy"和"expensive",但 std::array "same perfprmance as plain (c-style) arrays
- 一个C头文件可以被认为是一个接口吗
- 为什么const char*和const char[]作为函数参数被认为是等价的
- 为什么12.0==11.999999999999999999被认为是真的
- 这会被认为是糟糕的编程实践吗?
- 为什么这被认为是恒定的?
- 抽象类/接口中的空方法是否被认为是一种好的做法?
- 如果我具有调用其其他实例之一的超载函数,它是否被认为是递归功能
- std::unique_ptr可以被认为是一个monad吗?
- C++ 指向类的指针和/或引用是否被认为是"movable"?
- 使用自定义宏来简化 cin 和 cout 语句等内容被认为是更好还是更差
- 使用成员函数更改对象或返回并分配它是否被认为是更好的做法?
- 我很难修复我认为是双重免费的东西
- 使用 #define 被认为是"bad practice"吗?
- 是一个被认为是不同类型的班级内部的正向声明
- 这被认为是有效的C 11还是C 14?还是GCC/Clang弄错了
- 为什么这个嵌套的 lambda 不被认为是 constexpr?
- 限制C++中允许的模板参数是否被认为是不良样式?
- c++:"pointer to const"指向的对象是否被认为是不变的还是不可修改的?