你能帮我理解为什么编译器会给我这些错误信息吗?我相信易变物体的成员也是易变的。我来自here。但它表明,如果我们有一个结构:
struct someStruct
{
int d;
};
并且' p'定义如下:
volatile someStruct* volatile* p;
&(*p)->d
具有以下类型' int * volatile *'而不是' volatile int * volatile *'。以下是我正在处理的实际代码。
行(标记为错误1和2)是编译器抛出错误消息的地方:
#include <vector>
#include <windows.h>
using namespace std;
struct ThreadInfo
{
bool bWaiting = false;
bool bWorking = false;
};
struct lThreadInfo
{
ThreadInfo d;
lThreadInfo *pNextList = nullptr;
} volatile *volatile lThreads(nullptr);
thread_local ThreadInfo* currentThr(nullptr);
void CreateThread_(void (*pFunc)(ThreadInfo*))
{
volatile lThreadInfo* volatile* p = &lThreads;
for(; *p; p = &(*p)->pNextList); //**//error 1!**
*p = new lThreadInfo;
CreateThread(
nullptr, // default security attributes
0, // use default stack size
(long unsigned int (*)(void*))pFunc, // thread function name
&(*p)->d, // argument to thread function **//error 2!**
0, // use default creation flags
nullptr);
}
错误消息如下:
error 1: invalid conversion from 'lThreadInfo* volatile*' to 'volatile lThreadInfo* volatile*' [-fpermissive]
error 2: invalid conversion from 'volatile void*' to 'LPVOID {aka void*}' [-fpermissive]
注意:我知道volatile与线程安全无关,所以不要打扰告诉我。 Note1 :我在Windows上使用mingw64编译器。
答案 0 :(得分:2)
pNextList
访问路径 volatile
也是volatile
。但pNextList
是指针。 指针对象类型具有与之前相同的cv资格。
即
struct A
{
lThreadInfo* p;
};
someStruct volatile* volatile* p;
*p
是someStruct volatile* volatile
(*p)->d
是lThreadInfo* volatile
类型的左值。因此,在(*p)->d
类型中,您错过了lThreadInfo
和*
之间的易变。 [expr.ref] / 4:
如果
E2
是非静态数据成员且E1
的类型为“ cq1 vq1X
“,E2
的类型为” cq2 vq2T
“,表达式 指定由第一个指定的对象的命名成员 表达。如果E1
是左值,则E1.E2
是左值;如果E1
是xvalue,然后E1.E2
是xvalue;否则,它是一个prvalue。 让符号 vq12 代表 vq1 和 vq2 的“联合”;也就是说,如果 vq1 或 vq2 是volatile
,那么 vq12 为volatile
。同样,让符号 cq12 代表 cq1 和 cq2 ;也就是说,如果 cq1 或 cq2 是const
,然后 cq12 为const
。如果声明E2
是可变的 成员,然后E1.E2
的类型是“ vq12T
”。如果E2
不是 声明是一个可变成员,然后E1.E2
的类型是“ cq12 vq12T
“。
vq1 为volatile
, vq2 为空。因此 vq12 是volatile
。因此,表达式的类型为volatile T
,即lThreadInfo* volatile
。