C++ 能用静态施法摆脱常数为什么?

C++ 能用静态施法摆脱常数为什么?,c++,C++,我们知道,使用static_cast无法从表达式中删除常量。但今天我遇到了一个我能够做到的场景。我不知道它到底是怎么工作的。请找到下面的代码。此代码编译时没有任何错误,并给出正确的结果 为什么这段代码没有给出任何错误 void func1(double *ptr) { cout<<*ptr; } void main() { const double ab=2; func1(&static_cast<double>(ab));//I put &

我们知道,使用static_cast无法从表达式中删除常量。但今天我遇到了一个我能够做到的场景。我不知道它到底是怎么工作的。请找到下面的代码。此代码编译时没有任何错误,并给出正确的结果

为什么这段代码没有给出任何错误

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();
}

实际上,您并没有丢弃常量,因为它是有效的而不是指针。您只需要复制double,它是基本的,是一个微不足道的副本。

实际上,您的代码无法做到这一点……它无法编译。我得到了这个错误:

main.cpp:13:32:错误:一元和操作数需要左值

可能你的编译器太过宽容了。我试过使用GNU GCC版本4.8.1

消除常数的方法可能是使用常数投射,即使不建议这样做

void func1(double *ptr) 
{
  cout<<*ptr;
}

int main()
{
   const double ab=2;
   const double* ptr = &ab;
   func1(const_cast<double*>(ptr));

   return 0;
}
关于void main,它是

&static_-cast位更令人费解。有趣的是,如果你改变了双到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();
}
并尝试拨打以下电话:

func0<float>();     // No error
func0<double>();    // No error
func0<char>();      // C2101
func0<int>();       // C2101
func0<short>();     // C2101
func0<long>();      // C2101
func0<long long>(); // C2101
这个问题让我想起了允许你临时取一个类的地址。所以我尝试了一个类类型:

struct Foo
{
    Foo(int) {} // Foo(double) {} does not change the outcome
};

std::ostream& operator<<(std::ostream& os, const Foo&)
{
    return os;
}
调用func0时,我得到了预期的C4238警告,我总是使用“将警告转换为错误”选项集编译该警告:

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.在评论中提到的,这可能还与浮点类型不能用于常量表达式这一事实有关。不管怎样,这都是我遇到的最奇怪的错误之一。

编译和运行的事实让我质疑你的编译器。void main是不标准的,这样使用地址是不合法的。您是否在编译时带有警告而没有编译器扩展名?您应该无法获取地址或写入void main。您使用的编译器是什么?我使用的是visual studio 2008。请注意,此代码编译时没有任何错误或警告。下面是编译的快照:1>---编译已启动:项目:ch,配置:调试Win32---1>编译。。。1> 跳过。。。未检测到任何相关更改1>ch.cpp 1>生成日志保存在文件://h:\Learning\C++\ch\ch\Debug\BuildLog.htm 1>ch-0错误,0警告========生成:1成功,0失败,0最新,0跳过===========只是为了让您知道当以任何意义发送到编译器时,错误日志应该是什么样子:我已将void main更改为int main,如下所示,即使其工作void funct1double*ptr也是如此{coutBut为什么语句func1&static_castab;没有给出任何错误。而且我可以更改ab的值。请在下面的代码void func1double*ptr中找到{ cout@user1129251没有错误,因为存在编译器错误。但是即使此代码是合法的,它也会为您提供double副本的地址。您仍然没有修改ab。我正在使用visual studio 2008,并且它的编译成功,请在下面的编译报告快照中找到。1>---构建开始:项目:ch,配置:debug Win32---1>编译…1>跳过…未检测到任何相关更改1>ch.cpp 1>生成日志保存在文件:://h:\Learning\C++\ch\ch\Debug\BuildLog.htm 1>ch-0错误,0警告====================生成:1成功,0失败,0最新,0跳过========Visual Studio通常比GNU编译器更为宽松…事实上,它编译了这并不意味着它可以工作……它也可以工作并给出结果。但我认为这是一个编译器错误,正如上面在他的评论中解释的那样。我认为这是一个编译器错误。不过我注意到,如果我使用func1&static\u castab;的话,VS IDE 2013会突出显示一个由扭曲下划线转换的静态\u问题。如果我将鼠标移到static\u cast上它实际上告诉我,这是一个左值错误,但编译时没有错误,并且生成了输出。OP显示您对int是正确的。它给出了错误,但不是double,可能是编译器错误。有趣的是,可能与浮点类型无法在常量表达式中使用有关。谢谢,Elbert Mai,对于您有价值的输入,或者更具体地说,是一个有意的扩展 main.cpp:14:18: error: lvalue required as unary '&' operand func1(&static_cast(ab));
struct Foo
{
    Foo(int) {} // Foo(double) {} does not change the outcome
};

std::ostream& operator<<(std::ostream& os, const Foo&)
{
    return os;
}
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