在 Programming: Principles and Practice using C++ (第六次印刷)的第3章中,Stroustrup声明(第68页):“请注意sqrt()
未定义为{{ 1}}“即可。
这是一个基于该章的简单C ++程序:
int
鉴于上面的引用,我预计编译或运行该程序的过程会以某种方式失败。
令我惊讶的是,编译它(使用g ++(GCC)4.2.1)并成功运行它没有错误或警告,并产生以下完美不错的输出:
#include "std_lib_facilities.h"
int main()
{
int n = 3;
cout << "Square root of n == " << sqrt(n) << "\n";
}
因此我的问题是:如果Square root of n == 1.73205
没有为sqrt()
定义,那为什么上面的程序不会以某种方式失败?
答案 0 :(得分:5)
10被隐式转换为双。只要您拥有正确的sqrt函数原型,就会自动执行此操作。
编辑:被评论打败
答案 1 :(得分:4)
更新2
这个问题与一个完全重复的内容合并,看看这个,实际答案比任何人原先想象的要简单得多。当前版本的std_lib_facilities.h包含以下行:
inline double sqrt(int x) { return sqrt(double(x)); } // to match C++0x
为 int 创建一个特定的重载,以匹配现代编译器应该做的事情,将整数参数转换为double ,尽管此版本并未涵盖所有案件。
如果没有使用 std_lib_facilities.h 而原始逻辑仍然适用,尽管gcc-4.2
与原始问题中的 Visual Studio 2012 相比较旧但是4.1.2
版本专门针对整数情况使用__builtin_sqrt
。
原始
由于 2005 周围标准草案要求整数参数强制到 double ,所以draft C++ standard。如果我们查看26
Numerics库部分,然后转到涵盖26.8
标题的<cmath>
C库部分,它会指定 float , double 和 long double 的数学函数的重载,其中包含 8 :
除了数学函数的双重版本之外,C ++还添加了这些函数的float和long double重载版本,具有相同的语义。
对于ambiguous
情况int
,但标准要求提供足够的重载,以便整数参数强制到< EM>双。它包含在 11 段中(强调我的):
此外,还应有足够的额外过载来确保:
- 如果对应于double参数的任何算术参数的类型为long double,则对应于double参数的所有算术参数都有效地转换为long double。
- 否则,如果对应于double参数的任何算术参数具有double类型或整数类型,则则对应于double参数的所有算术参数将被有效地转换为double。
- 否则,与double参数对应的所有算术参数都具有float。
类型 醇>
更新
正如@nos所指出的那样,被调用的sqrt
版本可能来自math.h
标头而不是来自cmath
的重载,如果是这种情况并且存在可能实现已定义警告此处,如果唯一可用的版本为sqrt(double)
,那么可能将恢复为旧的 C样式行为意味着 int 将被隐式转换为双重。
我发现在gcc
和clang
上对此进行测试的一种方法是使用a
的 long 类型以及-Wconversion
标志如果我们只有sqrt(double)
可用,则会在我的平台上触发可能会改变价值的警告。实际上,如果我包含math.h
而不是cmath
,我们就可以发出此警告。虽然我无法在 clang 中触发此行为,这似乎表明这是实现依赖。
答案 2 :(得分:3)
由于隐式转化。 sqrt
的定义为double
,int
值可以隐式转换为类型double
的值。
(实际上很难阻止使用double
调用int
的函数。您可能会让编译器发出警告,但由于这通常是一种保值转换,即使这可能很难.C ++继承了C设计尽可能努力使代码工作,即使它需要扭曲。其他语言对此类事情要严格得多。)
答案 3 :(得分:2)
sqrt
是为double
定义的。 C ++允许您隐式地将int
转换为double
。
int n = 3;
double x = sqrt(n); // implicit conversion of n from int to double
当您将值用作函数参数或将其指定给变量时,可能会发生隐式转换。
第二种情况的一个例子是:
int n = 3;
double x = n; // implicit conversion of n from int to double
请注意,运算符也只是函数。因此,您还可以向int
添加double
,在调用实际添加内容之前将int
转换为double
:
int n = 3;
double x = 1.0;
double sum = n + x; // implicit conversion of n from int to double
答案 4 :(得分:1)
因为存在从int
到double
的隐式转换。
通过转换,您的代码将如下所示:
cout << "Square root of n == " << sqrt((double)n) << "\n";
答案 5 :(得分:1)
因为编译器实际上是自动(即“隐式”)将整数转换为double
(或者可能是long double
)并将该值发送到sqrt()
。这完全是正常和完全合法的。