Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.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++;可变成员函数_C++_Volatile_Member Functions - Fatal编程技术网

C++ C++;可变成员函数

C++ C++;可变成员函数,c++,volatile,member-functions,C++,Volatile,Member Functions,我是否需要将x和y声明为volatile,或者将所有成员变量自动视为volatile 我想确保编译器不会将“使用x填充”重新排序为“使用y填充” 编辑: 如果我将普通类型转换为volatile类型,会发生什么?这是否会指示编译器不重新排序对该位置的访问?我想在特殊情况下,将一个普通变量传递给一个参数不稳定的函数。我必须确保编译器不会用前面或后面的读写操作对调用重新排序。标记成员函数volatile就像标记它const;这意味着接收方对象被视为声明为volatile T*。因此,对x或y的任何引用

我是否需要将
x
y
声明为
volatile
,或者将所有成员变量自动视为
volatile

我想确保编译器不会将“使用
x
填充”重新排序为“使用
y
填充”

编辑:
如果我将普通类型转换为
volatile
类型,会发生什么?这是否会指示编译器不重新排序对该位置的访问?我想在特殊情况下,将一个普通变量传递给一个参数不稳定的函数。我必须确保编译器不会用前面或后面的读写操作对调用重新排序。

标记成员函数
volatile
就像标记它
const
;这意味着接收方对象被视为声明为
volatile T*
。因此,对
x
y
的任何引用都将被视为在成员函数中读取的
volatile
。此外,
volatile
对象只能调用
volatile
成员函数

也就是说,如果确实希望对它们的所有访问都被视为
volatile
,那么您可能希望将
x
y
标记为volatile,如下代码:

class MyClass
{
    int x, y;
    void foo() volatile {
        // do stuff with x
        // do stuff with y
    }   
};
#包括
分类栏
{
公众:
无效试验();
};
福班
{
公众:
void test()volatile{x.test();}
私人:
条形图x;
};
int main()
{
富富,;
foo.test();
返回0;
}
使用gcc编译时引发错误:

#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;
}
main.cpp:在成员函数“void Foo::test()volatile”中:
main.cpp:14:33:错误:调用“Bar::test()volatile”时没有匹配的函数
main.cpp:7:8:注:候选项为:void Bar::test()
由于
volatile
实例不能调用
non-volatile
方法,因此我们可以假设,是的,
x
y
将在方法中
volatile
,即使
MyClass
的实例未声明
volatile


注意:如果需要,可以使用
const_cast
删除
volatile
限定符;但是要小心,因为就像
const
一样,在某些情况下,这样做可能会导致未定义的行为。

您不必显式声明成员变量

根据标准文件9.3.2.3

类似地,volatile语义(7.1.6.1)在访问对象及其非静态对象时应用于volatile成员函数 数据成员。


因此,使用原始示例:

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>

如果我错了,请纠正我,但是volatile函数的语义不就是const函数的语义吗,因为你可以在非volatile对象上调用volatile函数,但是不是来自易失性对象的非易失性函数?@ereOn-在
g++
中的快速测试表明,您确实可以从-
volatile
对象调用
volatile
成员函数。
volatile std::string
s没有用处的原因是,如果字符串本身是
volatile
,它只能调用
volatile
成员函数,而这些函数没有$标准的4.4.1阐明了可以将T*隐式转换为volatile T*,$9.3.1.3表示
volatile
限定符会影响
指针,这表明如果您有
T
类型的对象,对于调用,
T*
类型的
this
指针可以转换为
volatile T*
。@templatetypedef:我颠倒了逻辑(现在才7点;我还需要一些睡眠;)。谢谢,现在修好了。您可以从
volatile
非volatile
实例调用
volatile
方法。但是如果您的实例是
易失性的
,您将无法调用
非易失性的
方法。@ereOn:所以,正如templatetypedef所说,它与
常量的情况完全相同。相关部分当然不是g++,但标准:第4.4.1条似乎向我表明,将
T*
隐式转换为
volatile T*
是完全合法的。还请注意,9.3.2.4明确指出,如果调用cv限定函数的对象表达式是“作为cv限定的或cv限定的小于成员函数”,则可以调用cv限定函数在这个区域中,
const
volatile
之间没有区别。至于强制转换:如果原始对象实际上被定义为volatile,并且您将此对象或其一个成员作为左值(基本上,在赋值的左侧)作为非volatile对象访问,本标准第7.1.5.1.7条规定,程序行为未定义。不要这样做,即使它在当前测试数据上与当前编译器的当前版本一起工作。在AFAICS中,强制转换对于只读访问是合适的,就像对于
const
.related一样
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
    } 
};