什么是*volatile*name = value?

mag*_*hat 2 c++ volatile

我在c ++语法中偶然发现了一些非常奇怪的东西.一个挥发性*类型.

这是我找到的代码(在Qt库中):

void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
if (receiver == 0) {
    qWarning(""QCoreApplication::postEvent: Unexpected null receiver"");
    delete event;
    return;
}

QThreadData * volatile * pdata = &receiver->d_func()->threadData; 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ WHAT IS THIS???
QThreadData *data = *pdata;
if (!data) {
    // posting during destruction? just delete the event to prevent a leak
    delete event;
    return;
}

// [...]
}
Run Code Online (Sandbox Code Playgroud)

我理解的是这个:

  • 我不能写volatile * QThreadData * pdata,因为那时我会得到一个编译器错误.这显然是因为对象不能volatile *,但指针可以.
  • pdata不是QThreadData *,它有一种QThreadData * volatile *类型.在尝试编译此代码时:int * volatile * x = new int(10);我会得到以下编译器错误:"无法在初始化时将'int*'转换为'int*volatile*'".

所以这些是我的问题:

  • 什么是什么类型QThreadData * volatile *,含义是volatile *什么?
  • 为什么是volatile *这种类型的一部分.为什么不只是类型QThreadData *与volatile *属性?

Vau*_*ato 6

声明QThreadData * volatile * pdata意味着它pdata是指向a的易失性指针的指针QThreadData.

通常,volatile意味着对象可以以超出编译器控制的方式进行更改.例如,如果它存储在由其他硬件写入的内存中.这意味着编译器必须在每次需要时从内存中读取值,而不是假设如果它之前已读取该值并且未对该内存位置进行更改,则该值仍然相同.

所以在这种情况下,pdata它本身并不易变.这意味着允许编译器假设pdata不会意外更改.但是,什么pdata指向可以意外地改变,它指向的是另一个指针.此外,其他易失性指针所指向的内容(实际的QThreadData)本身并不是易失性的.

在C++中,const并且volatile被视为非常相似.它们都表明该对象具有一些特殊属性.通过要求将这些特性与类型一起携带,可以更容易地避免某些错误.这更容易看到const,但同样的逻辑适用volatile.例如

void f(int *p)
{
    *p += 2;
    *p += 3;
}

int main()
{
    volatile int a = 5;
    f(&a); // error: can't convert volatile int * to int *
}
Run Code Online (Sandbox Code Playgroud)

由于函数f是与函数分开编译的main,编译器在编译函数时不会知道f它不应该假设*p不会意外地改变.没有这些知识,它可能会有效地改变代码

*p += 5;
Run Code Online (Sandbox Code Playgroud)

但这是错误的,因为*p可能会在两个添加之间发生变化.


Lig*_*ica 6

为了帮助解决你的困惑,你应该知道的第一件事是你有一个双指针类型.

接下来要说的是volatile-ness是类型的一部分,就像const-ness是类型的一部分:这个事实一起被称为cv-qualification.

[C++11: 7.1.6.1/7]: [注意: volatile是对实现的暗示,以避免涉及对象的激进优化,因为对象的值可能会被实现无法检测到的方式更改.有关详细语义,请参见1.9.一般来说,volatileC++中的语义与C语言相同._ - 尾注] _

这个短语volatile *不是任何一个特定的东西:它是类型中的两个令牌,可能意味着许多事情.


在这种情况下,你有一个QThreadData* volatile*,这是"指向易失性指针的QThreadData类型"的指针.从右到左阅读.

如果你剥掉volatile了,你就会留下一个QThreadData**.


如果你想要一个更简单的例子,这里有两个:

int volatile x = 5;
volatile int y = 6;
Run Code Online (Sandbox Code Playgroud)

看,就像const在这里,我们可以稍微使用cv-qualifier的顺序,因为没有歧义.

让我们稍微提升一下这个例子:

int volatile* p = new int volatile(5);
Run Code Online (Sandbox Code Playgroud)

现在我们有一个指向int volatile(再次,与a相同volatile int)的指针.该volatile应用左病房; 也就是说,而int不是*.

但我们也可能有一个易变的指针!比方说,指向非易失性int的易失性指针:

int* volatile p = new int(5);
Run Code Online (Sandbox Code Playgroud)

我不知道你所说的"财产"是什么意思.