注意してください、私は::abs()
ではなくstd::abs()
について話している
cplusplus.com Webサイト によると、stdlib.
を含めると、abs
は<cmath>
hCバージョンとは異なる動作をするはずです。
これは、このページからの抜粋です(::abs
ではなくstd::abs
を扱います):
double abs (double x);
float abs (float x);
long double abs (long double x);
Compute absolute value
/*
Returns the absolute value of x: |x|.
These convenience abs overloads are exclusive of C++. In C, abs is only declared
in <cstdlib> (and operates on int values).
The additional overloads are provided in this header (<cmath>) for the integral types:
These overloads effectively cast x to a double before calculations
(defined for T being any integral type).
*/
本当に???
ここではコンパイラと標準ライブラリの実装が異なるため、プログラムを新しいプラットフォームに移植するときに、これに悩まされてきました。
これが私のサンプルプログラムです:
#include <iostream>
//#include <stdlib.h>//Necessary inclusion compil under linux
//You can include either cmath or math.h, the result is the same
//#include <cmath>
#include <math.h>
int main(int argc, const char * argv[])
{
double x = -1.5;
double ax = std::abs(x);
std::cout << "x=" << x << " ax=" << ax << std::endl;
return 0;
}
そして、これがMSVC2010での結果です。
stdlib.h
も含まれていなくても、プログラムはコンパイルされます。math.h
とstdlib.h
は常に含まれているようです。行うx=-1.5 ax=1.5
(参照によると一見正しい)これがOSXでの結果です。
-Wall
フラグがあっても、コンパイル警告は発行されません(doubleからintへのキャストは通知されません)。 g++
をllvm-g++
に置き換えても結果は同じです。コンパイルには、math.h
またはcmath
を含める必要はありません。x=-1.5 ax=1
そして最後に、Linuxでの結果:
stdlib.h
が含まれていない場合、プログラムはコンパイルされません(最後に、stdlib
が自動的に含まれていないコンパイラが1つあります)。 double-> intキャストの場合、コンパイル警告は発行されません。x=-1.5 ax=1
ここに明確な勝者はありません。明白な答えは「std::abs
よりも::abs
を優先する」であることを私は知っていますが、私は疑問に思います:
abs
がstd
名前空間の外にダブルバージョンを自動的に提供する必要があると書かれている場合、cplusplus.com Webサイトはここにありますか?math.h
はサイレントに含まれています)?公式の参考文献によると...それは混乱です。 Pre-C++ 11およびC11:
公式には、<cmath>
を含めて::
には何も導入されていません。すべての関数はstd::
にありました。実際には、export
だけがあまり尊重されておらず、コンパイラが異なれば、動作も大きく異なります。 <cmath>
を含めた場合は、どこでもstd::
を使用したか、コンパイラーごとに異なるものを使用しました。
Cはオーバーロードを提供しませんでした:abs
はint
を取り、<stdlib.h>
で宣言され、fabs
はdouble
を取り、宣言されました<math.h>
で。
C++に<math.h>
を含めた場合、何が得られたかは明確ではありませんが、いずれの実装者も標準を気にしていないようでした(上記の最初のポイントを参照)...
大まかに言えば、<cmath>
を含め、すべての用途の前にstd::
を付けるか、<math.h>
を含め、浮動小数点のサポートが必要な場合はfabs
を使用しました( int
またはdouble
以外のタイプのさまざまなサフィックス)。
C++ 11とC11は、いくつかの新しい工夫を追加しました。
<cmath>
は、::
にもシンボルを導入できるようになりました(必須ではありません)。実装によって異なる可能性のあるもう1つのこと。 (ここでの目標は、既存の実装を適合させることでした。)
Cには新しいヘッダー<tgmath.h>
があり、コンパイラマジックを使用して、<math.h>
の関数をC++のようにオーバーロードされているかのように動作させます。 (したがって、abs
には適用されず、fabs
にのみ適用されます。)このヘッダーはnot C++に追加されました。これは、C++が適用されない明らかな理由によるものです。これにはコンパイラの魔法は必要ありません。
全体として、状況は少し悪化しており、上記の私の推奨事項は依然として有効です。 <math.h>
と<stdlib.h>
のいずれかを含め、abs
/fabs
とその派生物(例:labs
、fabsf
など)を使用します。 )排他的に、または<cmath>
を含め、std::abs
を排他的に使用します。それ以外の場合は、移植性の問題が発生します。