简介:volatile在C和C++中应用于函数声明时关键字的作用是什么?
细节:
我看到可以编译一个标记为的函数volatile.但是,我不确定这会阻止什么编译器优化(如果有的话).例如,我创建了以下测试用例:
volatile int foo() {
return 1;
}
int main() {
int total = 0;
int i = 0;
for(i = 0; i < 100; i++) {
total += foo();
}
return total;
}
Run Code Online (Sandbox Code Playgroud)
当我编译时clang -emit-llvm -S -O3 test.c(gcc也可以工作,但在我看来llvm IR更具可读性)我得到:
target triple = "x86_64-unknown-linux-gnu"
define i32 @foo() #0 {
ret i32 1
}
define i32 @main() #0 {
ret i32 100
}
Run Code Online (Sandbox Code Playgroud)
很明显,编译器能够优化掉函数调用,foo()以便main()返回一个常量,即使foo()标记为volatile …
我注意到std::atomic<T>类型的大多数成员函数被声明两次,一次使用volatile修饰符,一次没有(示例)).我检查了G ++标准库实现的源代码,我发现所有这些都是完全重复的,例如,
bool
load(memory_order __m = memory_order_seq_cst) const noexcept
{ return _M_base.load(__m); }
bool
load(memory_order __m = memory_order_seq_cst) const volatile noexcept
{ return _M_base.load(__m); }
Run Code Online (Sandbox Code Playgroud)
我找不到任何示例,其中volatile变体的行为与非行为不同volatile,返回类型或该类型的任何内容都不同.
这是为什么?我认为volatile也可以在不是的对象中调用成员函数volatile.所以声明和定义std::atomic::load(...) const volatile noexcept等应该足够了.
更新:
根据评论我的问题基本归结为:你能提供一个例子,其中一些使用非volatile实例(不一定是std::atomic)的调用会在以下两种情况下生成不同的程序集,
每个成员函数在有和没有相同的主体时出现volatile,
只有volatile变体存在?
这,假设编译器可以执行标准允许的任何优化(或者只是最高优化级别).
如果使用非volatile对象调用volatile成员函数会发生什么?
#include <iostream>
using namespace std;
class A
{
private:
int x;
public:
void func(int a) volatile //volatile function
{
x = a;
cout<<x<<endl;
}
};
int main()
{
A a1; // non volatile object
a1.func(10);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 假设我有以下非常简单的类:
class A
{
public:
static constexpr A make() { return A{}; }
constexpr A() : _v(0) {}
constexpr A& setV(int v) { _v = v; return *this; }
private:
int _v;
};
Run Code Online (Sandbox Code Playgroud)
如果我尝试按如下方式使用它:
int main()
{
volatile A a1;
a1.setV(10);
//OR
//The optimizer will optimize this chain of constexpr calls into a single "store" instruction
a1 = A::make().setV(10); //More chaining here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该代码将无法编译。
我理解为什么这是真的,基于:定义易失性类对象
我知道解决方案是添加一个额外的方法,如下所示:
class A
{
public:
constexpr A() : _v(0) {}
volatile A& …Run Code Online (Sandbox Code Playgroud)