提问人:i.stav 提问时间:7/23/2019 最后编辑:i.stav 更新时间:7/23/2019 访问量:365
指向成员的指针的 C++ 类内初始化使 MSVC 失败(但 GCC/Clang 工作)
C++ in-class initialization of pointer-to-member makes MSVC to fail (but GCC/Clang work)
问:
下面是一个非常简单的 C++ 代码:
#include <iostream>
struct A
{
int a;
constexpr static int A::* p = &A::a;
virtual void f() {}
};
int main()
{
A x; x.a = 0;
x.*(A::p) = 1234;
std::cout << x.a;
}
更令人震惊的是,这段代码显示了GCC,Clang和MSVC之间的不同结果。
我尝试了 4 个编译器
GCC:编译良好,打印.
1234
Clang :编译良好,打印 .
1234
MSVC(联机):编译失败。
使用 Visual Studio 2019 的 MSVC(本地):编译良好,打印 .(有趣的是,如果我删除它,它就会打印出来。
0
f()
1234
我不确定使用自己的成员对指向成员的指针进行类内初始化是否合法,但我相信这段代码应该打印.1234
在 Compiler Explorer 或 Rextester 上试用。
我不知道谁是对的。(至少 4.似乎是一个错误)
编辑 - 我发现 3 的差异。和 4.来自编译器选项。但是 和 no- 的结果仍然与 gcc 和 clang 不同。/permissive
/permissive
/permissive
答:
0赞
Windsting
7/23/2019
#1
更新
这是一个略微修改的代码,它似乎在 Visual Studio 2019 中按预期工作:
struct A
{
int a;
constexpr static int A::* p() { return &A::a; }
virtual void f() {}
};
using namespace std;
int main()
{
A x;
void* px = &x;
x.a = 0;
x.*(A::p()) = 1234;
cout << x.a << endl;
getchar();
}
更新结束
刚刚在 Visual Studio 2019 上尝试过,我将代码修改为:
#include <iostream>
struct A
{
int a;
constexpr static int A::* p = &A::a;
virtual void f() {}
};
struct B
{
int a;
constexpr static int B::* p = &B::a;
};
using namespace std;
void printBytes(void* p, size_t length = 16) {
uint8_t* pu = (uint8_t*)p;
cout << " ";
for (size_t i = 0; i < length; ++i) {
auto val = *(pu + i);
printf("%02x ", val);
}
cout << endl;
}
int main()
{
A x;
void* px = &x;
cout << "\nfor A:\n";
printBytes(px);
x.a = 0;
printBytes(px);
x.*(A::p) = 0x1234;
printBytes(px);
cout << x.a << endl;
B y;
void* py = &y;
cout << "\nfor B:\n";
printBytes(py);
y.a = 0;
printBytes(py);
y.*(B::p) = 0x1234;
printBytes(py);
cout << y.a << endl;
getchar();
}
输出为:
for A:
fc 9c 2c 01 cc cc cc cc cc cc cc cc 0f 40 04 09
fc 9c 2c 01 00 00 00 00 cc cc cc cc 0f 40 04 09
34 12 00 00 00 00 00 00 cc cc cc cc 0f 40 04 09
0
for B:
cc cc cc cc cc cc cc cc cc cc cc cc 60 fd 3d 01
00 00 00 00 cc cc cc cc cc cc cc cc 60 fd 3d 01
34 12 00 00 cc cc cc cc cc cc cc cc 60 fd 3d 01
4660
B 案例按预期工作,但对于 A 案例,上面的输出表明以下行:
x.*(A::p) = 0x1234;
写入到“指向虚拟功能表的指针”所在的位置。0x1234
因此,我认为 Visual Studio 2019 的编译器在具有虚拟成员函数的 struct(class and also )上的表达式(获取指向成员变量的指针)时犯了一个错误。&A::a
评论
0赞
i.stav
7/23/2019
井。。。那么这不是一个严重的错误..?
0赞
Windsting
7/23/2019
我不知道它有多严重,但我认为可以通过绕道来解决:改成constexpr static int A::* p = &A::a;
constexpr static int A::* PA() { return &A::a; }
评论