无效地使用不完整类型,引用vs指针
Invalid use of incomplete type, reference vs pointer
下面的代码可以在Visual 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;
}
下一个代码仍然在Studio中编译(并工作),但g++声明这是invalid use of incomplete type 'class A'
:
class A;
A& getRef(void); //the only change
char (&func(...))[2];
int main() {
bool isDefault = sizeof(func(getRef()))==2; //g++ error here
std::cout << isDefault << std::endl;
return 0;
}
这是一个根本错误的代码,应该被编译器拒绝(如果是这样,为什么VS编译器不产生任何警告)?或者在这里指针和引用有什么区别只是我没有意识到?
修改后的代码的关键方面是将对不完整类型的引用作为实际实参传递给省略号形式实参。
c++ 11§5.2.2/7,关于省略号的参数:”左值到右值(4.1),数组到指针(4.2),和函数到指针(4.3)的标准转换在实参表达式上执行。具有(可能是cv限定的)类型
std::nullptr_t
的参数被转换为类型void*
(4.10)。在这些转换之后,如果实参没有算术、枚举、指针、指向成员的指针或类类型,则程序是病态的。
对于左值到右值的转换,我们找到
c++ 11§4.1/1:<我>”非函数、非数组类型
T
的glvalue(3.10)可以转换为右值。如果T
是不完全类型,则需要进行这种转换的程序是病态的。
当我阅读它时,但这只是我的直觉解释,对T
的引用是T
类型的glvalue,在这里是不完整的,产生错误的代码。
无论func
的参数是什么,sizeof(func(getRef()))
都将等于2
。不需要对func
的参数求值来得到该答案。
来自c++ 11标准:
5.3.3运算符
1
sizeof
运算符返回其操作数的对象表示的字节数。操作数可以是未求值的操作数表达式(第5条),也可以是带括号的类型id。
在您的示例中,操作数是一个未求值的操作数表达式。编译器不需要计算func(getRef())
来得到sizeof(func(getRef()))
的值。
因此,我得出结论,g++
在它所需要的方面做得过火了。
看来c++对变量参数函数的处理是罪魁祸首。当func
被修改为
char (&func(A&))[2];
- 解析引用 |exe/dll vs lib
- 未定义的引用和运算符 << vs me
- 返回引用实例和非引用实例(return mystr & vs mystr)之间的区别是什么?
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- 返回字符串vs通过引用传递字符串以更新值
- 为什么 VS 无法将右值引用绑定到指针?
- 本机 Nuget 包安装在 VS 中,但没有为C++(本机)项目添加引用
- 此指针 - 按值返回 vs 按引用返回
- 返回一个C++引用变量 VS 返回一个变量
- 尝试将 std::vector<std::p air<T, U>> 转换为其左值引用时收到 VS 编译器警告 C4239
- 返回对int vs vs返回c 函数中的int的引用
- 通过引用传递的param Vs的值的内存消耗
- (右值引用)VS(常量左值引用)作为C++11中的函数参数
- C++实例 VS 指针 VS 引用
- 当我们在使用VS的C++项目中引用库作为附加依赖项时,会发生什么
- 传递参数的方式——值vs引用vs指针
- 从函数返回值:引用vs结构
- 将long类型的number传递给函数(引用vs值)(c++)
- 无效地使用不完整类型,引用vs指针
- 解引用vs数组访问