下面的代码在Visual Studio和g ++中编译和工作:
Revision: <g:meta name="app.version"/>
下一代码仍在Studio中编译(并且有效),但g ++声明这是class A;
A* getRef(void);
char (&func(...))[2];
int main() {
bool isDefault = sizeof(func(getRef()))==2;
std::cout << isDefault << std::endl; //prints 1
return 0;
}
:
invalid use of incomplete type 'class A'
这是一个根本错误的代码,应该被编译器拒绝(如果是这样,为什么VS编译器不会产生任何警告)?或者在我不知道的情况下指针和引用之间是否存在一些差异?
答案 0 :(得分:4)
修改后的代码的关键方面是对不完整类型的引用作为实际参数传递给省略号形式参数。
C ++11§5.2.2/ 7,关于省略号的参数:“左值到右值(4.1),数组到指针(4.2),以及 函数到指针(4.3)对参数表达式执行标准转换。具有(可能是cv-qualified)类型
std::nullptr_t
的参数将转换为类型void*
(4.10)。在这些转换之后,如果参数没有算术,枚举,指针,成员指针或类类型,则程序格式不正确。
然后,对于左值到右值的转换,我们找到
C ++11§4.1/ 1:“非功能非数组类型
T
的glvalue(3.10)可以转换为prvalue。如果T
是不完整的类型,则需要进行此转换的程序格式不正确。
当我读到它时,这只是我的直觉解释,对T
的引用是T
类型的glvalue,这里不完整,会产生格式错误的代码。
答案 1 :(得分:2)
无论func
sizeof(func(getRef()))
的论点是2
还是等于func
。无需评估sizeof
的参数即可得出答案。
来自C ++ 11标准:
5.3.3尺寸
1
func(getRef())
运算符产生其操作数的对象表示中的字节数。操作数是表达式,它是未评估的操作数(第5条),或带括号的 type-id 。
在您的情况下,操作数是一个表达式,它是一个未评估的操作数。编译器无需评估sizeof(func(getRef()))
以获得g++
的值。
因此,我得出结论,func
在需要的内容方面过度。
似乎g ++对变量参数函数的处理是罪魁祸首。当char (&func(A&))[2];
被修改为
class Comment < ActiveRecord::Base
has_many :children_comments,
class_name: 'Comment',
foreign_key: 'parent_comment_id'
belongs_to :user
belongs_to :parent_comment,
class_name: 'Comment',
foreign_key: 'parent_comment_id'
end
在http://ideone.com/YQD9v0处查看它。