我在c ++语法中偶然发现了一些非常奇怪的东西。 volatile *类型。
这是我找到的代码(在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;
}
// [...]
}
我理解的是:
volatile * QThreadData * pdata
,因为那时我会遇到编译错误。这显然是因为对象不能是volatile *
,而是指针可以。pdata
不是QThreadData *
,而是QThreadData * volatile *
类型。在尝试编译此代码时:int * volatile * x = new int(10);
我会得到以下编译器错误:“无法在初始化中将'int *'转换为'int * volatile *'。所以这些是我的问题:
QThreadData * volatile *
是什么类型volatile *
是什么意思?volatile *
是类型的一部分。为什么QThreadData *
类型不具有volatile *
属性?答案 0 :(得分:6)
声明QThreadData * volatile * pdata
表示pdata
是指向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 *
}
由于函数f
是与函数main
分开编译的,编译器在编译函数f
时不会知道它不应该假设*p
意外地未发生变化。没有这方面的知识,它可能会有效地改变代码
*p += 5;
但这是错误的,因为* p可能会在两次添加之间发生变化。
答案 1 :(得分:6)
为了帮助解决您的困惑,您首先要知道的是您有双指针类型。
接下来要说的是volatile
- ness是类型const
的一部分 - ness是类型的一部分:这个事实被称为 cv-qualification
[C++11: 7.1.6.1/7]:
[注意:volatile
是对实现的暗示,以避免涉及对象的激进优化,因为对象的值可能会被无法通过实现。有关详细语义,请参见1.9。通常,volatile
的语义在C ++中应该与它们相同 在C. _ - 尾注] _
短语volatile *
不是任何一个特定的东西:它是类型中的两个标记,可能意味着许多事情。
在这种情况下,您有一个QThreadData* volatile*
,它是“指向QThreadData
”类型的易失性指针的指针。从右到左阅读。
如果您将volatile
删除,则会留下QThreadData**
。
如果你想要一个更简单的例子,这里有两个:
int volatile x = 5;
volatile int y = 6;
请参阅const
,这里我们可以稍微使用 cv-qualifier 的顺序,因为没有歧义。
让我们稍微提升一下这个例子:
int volatile* p = new int volatile(5);
现在我们有一个指向int volatile
的指针(再次,与volatile int
相同)。 volatile
适用于左病房;也就是说,int
,而不是*
。
但我们也可能有一个易变的指针!比方说,指向非易失性int的易失性指针:
int* volatile p = new int(5);
我不知道你所说的“财产”是什么意思。