在使用指向成员的指针的过程中,我遇到了一种行为,这种行为似乎与我有些矛盾,有些违反直觉。考虑以下虚拟结构:
struct foo {
int x;
double d;
};
和以下main()
:
int main() {
int foo::* ptr = &foo::x;
double foo::* ptr2 = &foo::d;
}
在这里,我们没有任何异常-两个指向const
成员的指针。该代码可以很好地编译。
引起我注意的是,当我们添加const
时,情况有所变化。考虑以下代码:
int main() {
// no int or double after const
const foo::* ptr = &foo::x;
}
代码在 GCC 8.2.0 1 上可以正常编译。注意,我没有指定指针指向的数据类型。
但是,此代码:
int main() {
// notice the only change - "d" instead of "x"
const foo::* ptr = &foo::d;
}
无法编译,并出现以下错误:
错误:初始化
double foo::*
时无法将'const int foo::*
'转换为'const foo::* ptr = &foo::d;
'
这很有趣-它暗示默认情况下,const
指向成员的指针被隐式声明为指向某个int
成员。这是正确的标准行为吗?
值得注意的是,如果我们放下const
,这两行都会产生错误:
int main() {
foo::* ptr1 = &foo::x;
foo::* ptr2 = &foo::d;
}
采用以下形式:
错误:“
*
”令牌之前存在预期的不合格ID错误:'
ptr1
'|未在此范围内声明“ptr2
”
所以问题是-如果没有另外指定,标准是否指定const
指向成员的指针隐式指向int
,还是非标准行为? (GCC扩展程序或GCC错误)。
1 编辑:我正在使用MinGW的GCC-this特定版本。
答案 0 :(得分:2)
该代码在ISO C ++中不正确,但是-fms-extensions
启用了“隐式int”行为,gcc会自动启用该行为以定位Microsoft ABI。
您可以使用-fno-ms-extensions
将其关闭。
我检查了源代码(gcc-9.1.0 / gcc / cp / decl.c),结果发现在ms-extensions
模式下,隐式int 的警告已禁用- -实际上会产生任何可能生成消息ISO C++ forbids declaration of %qs with no type
的任何内容,其中int
被用作类型。
这可能比解决它要解决的任何问题所需的锤子更大。例如,您还可以查看与const *x;
或const f();
的差异。
我尝试将-fno-ms-extensions
添加到我使用mingw-w64的一些“大型” Windows项目的构建中,并且没有出现错误,因此将这个标志作为问题可能是一个好习惯习惯(甚至向mingw-w64提交补丁以默认关闭它)。
答案 1 :(得分:1)
所以问题是-如果我们不另外指定,标准是否指定const指向成员的指针隐式指向int
不。 GCC通常会以简单的英语给出答案,并且拒绝编译(如果使用-fpermissive
,则发出警告):
error: ISO C++ forbids declaration of 'ptr' with no type
它不是扩展名。允许在-fpermissive
模式下使用,以使非常旧的旧代码可编译。
MinGW-w64随附的GCC似乎没有捕获此错误。我不知道这是否是故意的。