Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这里需要挥发油吗?_C++_Volatile - Fatal编程技术网

C++ 这里需要挥发油吗?

C++ 这里需要挥发油吗?,c++,volatile,C++,Volatile,根据约翰尼斯的宝贵回答,编辑并完善了我的问题 bool b = true; volatile bool vb = true; void f1() { } void f2() { b = false; } void(* volatile pf)() = &f1; //a volatile pointer to function int main() { //different threads start here, some of which may change pf

根据约翰尼斯的宝贵回答,编辑并完善了我的问题

bool b = true;
volatile bool vb = true;    
void f1() { }
void f2() { b = false; }

void(* volatile pf)() = &f1; //a volatile pointer to function

int main()
{
   //different threads start here, some of which may change pf 
   while(b && vb)
   {
      pf();
   }
}
所以,让我们暂时忘记同步。问题是b是否必须声明为不稳定的。我已经阅读了标准,并大致了解了volatile语义的正式定义(我甚至几乎能理解它们,单词几乎是关键)。不过我们还是随便说说吧。如果编译器在循环中发现b无法更改,那么除非b是易失性的,否则它可以对其进行优化,并假定它等同于
while(vb)
。问题是,在这种情况下pf本身是易失性的,那么编译器是否可以假设即使b不是易失性的,b也不会在循环中改变

请不要评论和回答这段代码的风格,这不是一个真实的例子,这是一个实验性的理论问题。 除了回答我的问题外,您认为我误解了volatile的语义,我们非常欢迎您的评论和回答

我希望我的问题是清楚的。短暂性脑缺血发作

再次编辑:
这个怎么样

bool b = true;
volatile bool vb = true;
void f1() {}
void f2() {b = false;}
void (*pf) () = &f1;

#include <iosrteam>
int main()
{
   //threads here

   while(b && vb)
   {
      int x;
      std::cin >> x;
      if(x == 0)
         pf = &f1;
      else
         pf = &f2;    
      pf();
   } 
}
bool b=true;
volatile bool vb=true;
void f1(){}
void f2(){b=false;}
无效(*pf)(=&f1;
#包括
int main()
{
//这里的线程
while(b&vb)
{
int x;
标准:cin>>x;
如果(x==0)
pf=&f1;
其他的
pf=&f2;
pf();
} 
}
这两个项目之间有主要区别吗。如果是,有什么区别

问题是,在这种情况下pf本身是易失性的,那么编译器是否可以假设即使b不是易失性的,b也不会在循环中改变

它不能,因为您说其他线程可能会更改
pf
,如果while循环调用
pf
,这会间接更改
b
。因此,虽然理论上不要求正常读取
b
,但实际上必须读取它以确定是否应短路(当
b
变为
false
时,它不得再次读取
vb


对第二部分的回答

在这种情况下,
pf
不再是易失性的,因此编译器可以去掉它,并看到
f1
有一个空的主体,
f2
b
设置为false。它可以优化
main
,如下所示

int main()
{
   // threads here (which you say can only change "vb")

   while(vb)
   {
      int x;
      std::cin >> x;
      if(x != 0)
         break;    
   } 
}

对旧版本的回答

允许编译器优化循环的一个条件是循环不访问或修改任何易失性对象(请参阅n3126中的[stmt.iter]p5)。你在这里这样做,所以它不能优化循环。在C++03中,编译器甚至不能优化循环的非易失性版本(但编译器还是这样做了)


请注意,能够优化它的另一个条件是循环不包含同步或原子操作。但在多线程程序中,无论如何都应该存在这样的问题。因此,即使你摆脱了那种
易失性
,如果你的程序编码正确,我也不认为编译器可以完全优化它。

易失性只会伤害到你,如果你认为你可以从一种无法完成的优化中获益,或者如果它传达了一些不真实的信息

在您的例子中,您说过这些变量可以被其他线程更改。在阅读代码时,当我看到volatile时,这是我的假设,所以从维护人员的角度来看,这很好——它给了我额外的信息(这是真的)

我不知道这些优化是否值得尝试挽救,因为您说过这不是真正的代码,但如果不是,那么就没有任何理由不使用volatile

不使用volatile会导致不正确的行为,因为优化正在改变代码的含义


我担心对编译器的标准和行为的细节进行编码,因为这类事情可能会发生变化,即使它们不会发生变化,代码也会发生变化(这可能会影响编译器)——因此,除非您在这一特定代码上寻求微优化改进,我就不这么说了。

< P>在当前的C++标准中,在Value<代码>中的确切要求,如我所理解的,并不是完全由标准定义的,因为标准实际上不涉及多线程。它基本上是一个编译器提示。因此,我将讨论典型编译器中发生的情况

首先,假设编译器独立编译函数,然后将它们链接在一起。在这两个示例中,都有一个循环,在其中检查变量并调用函数指针。在该函数的上下文中,编译器不知道该函数指针后面的函数将执行什么操作,因此在调用它之后,它必须始终从内存重新加载
b
。因此,
volatile
与此无关

将其扩展到您的第一个实际情况,并允许编译器进行整个程序优化,因为
pf
是不稳定的,编译器仍然不知道它将指向什么(它甚至不能假设它是
f1
f2
!),因此,同样不能对函数指针调用中未修改的内容做出任何假设,因此
volatile
on
b
仍然是不相关的

您的第二种情况实际上更简单--
vb
,因为它是一条红鲱鱼。如果消除了这一点,您可以看到,即使在完全单线程语义中,函数指针调用也可能修改
b
。您没有使用未定义的行为执行任何操作,因此程序必须在没有
volatile
的情况下正确运行--请记住,如果您没有考虑使用外部线程调整的情况,
volatile
是不可操作的。因此,没有