我们知道使用static_cast我们无法从表达式中删除constness。但是今天我遇到了一个可以做到这一点的场景。我无法弄清楚它是如何运作的。请在下面找到代码。此代码编译时没有任何错误,并给出正确的结果。
为什么这段代码没有出错?
void func1(double *ptr)
{
cout<<*ptr;
}
void main()
{
const double ab=2;
func1(&static_cast<double>(ab));//I put & operator infront of static_cast and this works.
cin.get();
}
答案 0 :(得分:2)
关于void main()
,它是a Microsoft-specific extension to the Visual C++ compiler。
&static_cast<double>()
位更令人费解。有趣的是,如果将double
更改为int
,则Visual C ++编译器(2013)会正确报告错误:
#include <iostream>
void func1(int* ptr)
{
std::cout << *ptr;
}
int main()
{
const int ab = 2;
func1(&static_cast<int>(ab));
std::cin.get();
}
上面的代码段给出了:
1> Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x64 1> Copyright (C) Microsoft Corporation. All rights reserved. 1> 1> main.cpp 1>main.cpp: error C2101: '&' on constant 1>main.cpp: error C2664: 'void func1(int *)' : cannot convert argument 1 from 'int' to 'int *' 1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
当我用int
或int main()
替换double
的所有实例(float
除外),令人惊讶的是它会编译。完成int
,short
,char
或long
后,它会正确报告C2101。
为了进一步探索,我已将您的功能转换为模板:
#include <iostream>
template<typename T>
void func1(T* ptr)
{
std::cout << *ptr;
}
template<typename T>
void func0()
{
const T ab = 2;
func1<T>(&static_cast<T>(ab));
}
尝试拨打以下电话:
func0<float>(); // No error
func0<double>(); // No error
func0<char>(); // C2101
func0<int>(); // C2101
func0<short>(); // C2101
func0<long>(); // C2101
func0<long long>(); // C2101
最后5个版本的unsigned
版本也会产生C2101错误。我可以使用Visual C ++ 2013可靠地重现这一点。当T
是float
或double
时,似乎没有给出错误。 GCC对func0
的所有调用产生编译错误:
main.cpp:14:18: error: lvalue required as unary '&' operand func1(&static_cast(ab));
这个问题让我想起a non-standard extension in Visual C++,它允许你临时取一个班级的地址。所以我尝试了类类型:
struct Foo
{
Foo(int) {} // Foo(double) {} does not change the outcome
};
std::ostream& operator<<(std::ostream& os, const Foo&)
{
return os;
}
当调用func0<Foo>()
时,我收到预期的C4238警告(我总是使用&#34编译;将警告转为错误&#34;选项集):
1> Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x64 1> Copyright (C) Microsoft Corporation. All rights reserved. 1> 1> main.cpp 1>main.cpp: error C2220: warning treated as error - no 'object' file generated 1> main.cpp: see reference to function template instantiation 'void func0(void)' being compiled 1>main.cpp: warning C4238: nonstandard extension used : class rvalue used as lvalue
鉴于这些结果,这让我觉得这确实是一个编译器错误,甚至VS2013中的C ++编译器都表现出这种行为。它可能与C4238有关。作为T.C.在评论中提到,它也可能与浮点类型不能使用常量表达式这一事实有关。无论哪种方式,这都是我遇到过的更为奇怪的错误之一。
答案 1 :(得分:1)
你实际上并没有丢弃const
,因为它是有效的而不是指针。你只是制作double
的副本,它是原始的,是一个微不足道的副本。
答案 2 :(得分:0)
实际上,您的代码无法执行此操作....它无法编译。我收到此错误:
main.cpp:13:32:错误:左值作为一元&amp;操作数
可能你的编译器太宽容了。我尝试使用http://www.compileonline.com/compile_cpp_online.php
中的GNU GCC版本4.8.1删除constness的方法是使用const_cast
(即使重新建议也不建议这样做......)
void func1(double *ptr)
{
cout<<*ptr;
}
int main()
{
const double ab=2;
const double* ptr = &ab;
func1(const_cast<double*>(ptr));
return 0;
}