C++ 指向成员的常量指针是否默认指向int?
在使用指向成员的指针时,我遇到了一种行为,这种行为似乎有点不一致,对我来说有点违反直觉。考虑下面的虚拟结构:C++ 指向成员的常量指针是否默认指向int?,c++,syntax,language-lawyer,variable-declaration,pointer-to-member,C++,Syntax,Language Lawyer,Variable Declaration,Pointer To Member,在使用指向成员的指针时,我遇到了一种行为,这种行为似乎有点不一致,对我来说有点违反直觉。考虑下面的虚拟结构: struct foo { int x; double d; }; 以及以下main(): 在这里,我们没有什么不寻常的地方——两个指向const成员的指针。代码编译得很好 引起我注意的是,当我们添加const时,情况会有一点变化。考虑下面的代码: int main() { // no int or double after const const foo
struct foo {
int x;
double d;
};
以及以下main()
:
在这里,我们没有什么不寻常的地方——两个指向const
成员的指针。代码编译得很好
引起我注意的是,当我们添加const
时,情况会有一点变化。考虑下面的代码:
int main() {
// no int or double after const
const foo::* ptr = &foo::x;
}
代码在GCC 8.2.0上编译良好。请注意,我没有指定指针将指向的数据类型
但是,该代码:
int main() {
// notice the only change - "d" instead of "x"
const foo::* ptr = &foo::d;
}
未能编译,出现以下错误:
错误:无法在初始化中将“double-foo::*
”转换为“const-int-foo::*
”代码>
这很有趣-它表明,默认情况下,指向成员的const
指针隐式声明为指向某个int
成员。这是正确的、标准的行为吗
值得注意的是,如果我们删除常量
,这两行都会产生错误:
int main() {
foo::* ptr1 = &foo::x;
foo::* ptr2 = &foo::d;
}
形式如下:
错误:在“*
”标记之前应为非限定id
错误:“ptr1
”|“ptr2
”未在此范围内声明
所以问题是-如果我们没有另外指定,标准是否指定const
指向成员的指针隐式指向int
,或者这是一种非标准行为?(GCC扩展或GCC错误)
1EDIT:我正在使用来自MinGW的GCC-特定构建 所以问题是-如果我们没有另外指定,标准是否指定指向成员的常量指针隐式指向int 不可以。GCC通常会用简单的英语给出答案,并拒绝编译(如果您使用的是
-fpermissive
),则会发出警告:
错误:ISO C++禁止声明“没有类型”PTR
它不是一个扩展。允许在-fpermissive
模式下使用,以保持非常旧的遗留代码可编译
但是,MinGW-w64提供的GCC似乎没有捕捉到这个错误。我不知道它是否有意。 < P>在ISO C++中代码是错误的,但是“隐式INT”行为是通过GCC自动启用针对微软ABI的。 您可以使用
-fno ms extensions
将其关闭
我检查了源代码(GCC-91.0/Gcc/CP/DELL.C),结果发现在
const*x的差异代码>或常数f()代码>例如
我尝试将-fno ms extensions
添加到我使用mingw-w64的一些“大型”Windows项目的构建中,但没有出现任何错误,因此,作为习惯,使用此标志可能是一种好的做法(或者甚至向mingw-w64提交一个补丁,默认情况下关闭它……。“代码在GCC 8.2.0上编译得很好”呃,不,不是。您是使用-fpemmissive
编译的吗?我强烈建议不要这样做。通常当没有给出类型时,会假定int。我想这就是为什么它对int有效,或者更确切地说是对double有效,但不是double。@Chipster我有没有提出其他建议?我不打算这么做。@Chipster啊,是的,我知道,但谢谢你。问题是我编译时没有-fppermission
。它在godbolt上确实失败了,但在我的构建(我使用的是[here]-STL的构建中的MinGW),它仍然可以很好地编译,即使没有编译器标志。那么,你认为这是MinGW的一个bug吗?@Fureeish,你肯定应该把它包括在问题中。我可以在我的MinGW的GCC 8.1上复制它。@fureish它也发生在我自己在Linux上构建的MinGW GCC(8.3.0)交叉编译器上。似乎是一个一般性的mingw问题(或者更准确地说,mingw-w64)。@Fureeish在问题下的评论中说“它实际上使用-fppermission
编译,没有它就不会编译”,但现在你说它不使用-fppermission编译;这是哪一个?@KeithThompson这似乎是意料之中的事。见M.M.的答案。我将发布我的Cygwin bug报告的后续内容。我很失望,在默认启用了-fms扩展的系统上,g++-std=c++11-pedantic
无法生成所需的诊断。我可能会向gcc提交一个bug。有趣的是,gcc-fms extensions
警告C中的隐式int
。您知道在默认情况下如何为MinGW和其他Windows版本打开该选项吗?这是一个配置选项,还是他们修改了gcc源代码?(我正在试图确定这是否是一个gcc错误。)@KeithThompson您可以通过在github上查找mingw-w64项目来检查源代码。好吧,他们根本没有修改gcc源代码,但他们显然在某个地方打开了这个选项。我不认为向gcc报告错误是有道理的,因为这似乎是预期的行为,但最好对ms extensions
所做的事情进行更细粒度的控制(例如,如果他们允许-Wimplicit int
否决-fms扩展
。在建议更改之前,人们希望熟悉用例;我不是。可能有一些流行的代码库需要此标志。他们已经有一个过滤器,如果它被标识为系统头,则不会对此发出警告,可能是t不能正确识别windows标题?谁知道呢。@KeithThompson进一步检查后发现,标志控件在GCC源代码中;如果目标ABI是Microsoft的,它将启用它。
int main() {
foo::* ptr1 = &foo::x;
foo::* ptr2 = &foo::d;
}
error: ISO C++ forbids declaration of 'ptr' with no type