2011-01-28 11 views
27
class MyClass 
{ 
    int x, y; 
    void foo() volatile { 
     // do stuff with x 
     // do stuff with y 
    } 
}; 

Czy muszę zadeklarować "x" i "y" jako zmienne lub czy wszystkie zmienne składowe będą traktowane jako zmienne automatycznie?C++ lotne funkcje członkowskie

Chcę się upewnić, że "stuff with" x "" nie jest porządkowany przez "stuff with" y "przez kompilator.

EDYCJA: Co się stanie, jeśli rzucę zwykły typ do typu lotnego? Czy poinstruuje to kompilator, aby nie porządkował dostępu do tej lokalizacji? Chcę przekazać normalną zmienną w specjalnej sytuacji do funkcji, której parametr jest niestabilny. Muszę się upewnić, że kompilator nie zmienia kolejności tego połączenia z wcześniejszymi lub następującymi odczytami i zapisami.

+2

wielkie pytanie. –

+0

powiązane http: // stackoverflow.com/questions/2444734/what-is-purpose-of-a-volatile-member-function-in-c –

Odpowiedz

22

Oznaczanie funkcji składowej volatile przypomina jej oznaczenie jako const; oznacza to, że obiekt odbiorcy traktowany jest tak, jakby był zadeklarowany jako volatile T*. W konsekwencji każde odniesienie do x lub y będzie traktowane jako funkcja odczytu. Co więcej, obiekt volatile może wywoływać tylko funkcje składowe volatile.

Powiedział, że może warto zaznaczyć x i yvolatile każdym razie, jeśli naprawdę chcesz wszystko dostęp do nich mają być traktowane jako volatile.

4

Poniższy kod:

#include <iostream> 

class Bar 
{ 
    public: 

     void test(); 
}; 

class Foo 
{ 
    public: 

     void test() volatile { x.test(); } 

    private: 

     Bar x; 
}; 

int main() 
{ 
    Foo foo; 

    foo.test(); 

    return 0; 
} 

zgłasza błąd przy kompilacji z gcc:

main.cpp: In member function 'void Foo::test() volatile': 
main.cpp:14:33: error: no matching function for call to 'Bar::test() volatile' 
main.cpp:7:8: note: candidate is: void Bar::test() <near match> 

A ponieważ instancja volatile nie można wywołać metodę non-volatile, możemy założyć, że tak, x i y będą w metodzie volatile, nawet jeśli wystąpienie MyClass nie zostanie zadeklarowane jako volatile.

Uwaga: możesz usunąć kwalifikator volatile, korzystając z const_cast<>, jeśli zajdzie taka potrzeba; należy jednak zachować ostrożność, ponieważ podobnie jak w niektórych przypadkach może to prowadzić do niezdefiniowanego zachowania.

+0

Popraw mnie jeśli się mylę, ale to nie semantyka zmiennych funkcji, takich jak const funkcjonuje w tym, że możesz wywoływać ulotną funkcję na nieulotnym obiekcie, ale nie jest to funkcja nieulotna z niestabilnego obiektu? – templatetypedef

+0

@ ereOn- Szybki test w 'g ++' sugeruje, że rzeczywiście można wywoływać funkcje 'volatile' z obiektów' -ololatile'. Powodem, dla którego 'volatile std :: string's jest bezużyteczny, jest to, że jeśli sam napis jest" volatile ", może on wywoływać tylko funkcje' volatile', których nie ma. 4.4.1 standard wyjaśnia, że ​​można konwertować T * na niestabilny T * niejawnie, a 9.3.1.3 mówi, że kwalifikator 'volatile' wpływa na" ten "wskaźnik, co sugeruje, że jeśli masz obiekt typu' T ',' '' wskaźnik typu 'T *' może zostać przekonwertowany na 'volatile T *' dla wywołania. – templatetypedef

+0

@templatetypedef: Odwróciłem logikę (jest tu tylko 7 rano, nadal potrzebuję snu;)). Dzięki, jest teraz naprawiony. Możesz wywołać metodę 'volatile' zarówno z instancji' volatile', jak i 'non volatile'. Ale jeśli twoja instancja jest "lotna", nie będziesz w stanie wywoływać metod "nieulotnych". – ereOn

6

Nie mają zadeklarować zmienne składowe wyraźnie ..

od standardowych docs 9.3.2.3,

Podobnie lotne semantyka (7.1.6.1) stosuje się w lotnych funkcjach składowych podczas uzyskiwania dostępu do obiektu i jego niestatycznych elementów danych.

1

Więc użyciu oryginalnego przykład:

class MyClass 
{ 
    int x, y; 
    void foo() volatile { 
     // do stuff with x 
     // do stuff with y 
     // with no "non-volatile" optimization of the stuff done with x, y (or anything else) 
    } 
    void foo() { 
     // do stuff with x 
     // do stuff with y 
     // the stuff done with x, y (and anything else) may be optimized 
    } 
};