简体   繁体   中英

C++ volatile object, nonvolatile member

As in the question: let's say I have a small piece of code like this:

  #include <iostream>
  using namespace std;

  struct foo {
      int a; 
      foo() : a(12) {};
  };  

  int
  main()
  {
      volatile foo x;
      return 0;
  }   

compiled with g++ -g -O2 it turns out, that x initialization is optimized away.

That one however:

  #include <iostream>
  using namespace std;

  struct foo {
      volatile int a; 
      foo() : a(12) {};
  };  

  int
  main()
  {
      volatile foo x;
      return 0;
  }   

calls the constructor.

If I try to use the variables inside the code, (ie. cout << foo.a << endl; ) the assembly output is equivalent in both cases.

Do I get the following right, that:

In the first case, there's no access to the struct at all, so it gets optimized away completely.

In the second one, struct's field is indicated as the one possible to change also during the construction and for that reason foo() is called no matter what.

Added: I've tried fiddling with the above code: calling things like while(foo.a--); works as expected, it actually happens instead of being deleted/replaced by result during optimization, thus it seems the volatile is actually inherited, yet the ctor behaves in this strange (or at least unexpected at first) way.

EDIT number 2:

I checked it with clang and MSVC and it behaves the same way as in gcc.

My understanding is as follows (and I am not sure about it):

In C++ volatile keyword forces compiler not to optimize seemingly redundant loads and stores to memory, ie if you have such example code:

int x = 5;
x = 6;

It will not be changed to:

int x = 6;

This is because x could be pointing to some address in memory, that is read by others, while you don't read it really in your program (imagine that you are sending some configuration over USART to microcontroller by writing to certain memory address, and the microcontroller reads it's configuration from that address - if compiler was to optimize writes to this memory, then whole program would malfunction).

Another thing that one must remember is that when instance of a class is declared with volatile specifier, then its members inherit this specifier (as Igor Tandetnik pointed out in comment, referring to C++ Standard). But this is not the whole truth, because in order to get volatile behaviour, you would have to call member functions, that are marked as volatile - similar to marking member function as const (please see this: http://www.devx.com/tips/Tip/13671 ). Because AFAIK ctors/dtors cannot be marked with volatile keyword (as in Defining volatile class object ), you would have to change your code a bit (perhaps invoking volatile member function from within ctor would do the thing, but this is only a guess).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM