31

私が話しているのは::abs()ではなく、注意してくださいstd::abs()

cplusplus.com の Web サイトによると、 h C バージョンでabsは動作が異なるはずです。stdlib.<cmath>

::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;
}

MSVC 2010 での結果は次のとおりです。

  • MSVC 2010 ではコンパイル警告は表示されず、 math.h もstdlib.h:も含まれていなくmath.hても、プログラムはコンパイルさstdlib.hれます。
  • プログラムの出力は次のとおりです。x=-1.5 ax=1.5(参照によると一見正しい)

OSXでの結果は次のとおりです。

  • フラグを使用しても、コンパイルの警告は発行されません-Wall(double から int へのキャストは通知されません)。に置き換えg++ても結果は同じですllvm-g++math.horを含めることはcmath、コンパイルには必要ありません。
  • プログラムの出力は次のとおりです。x=-1.5 ax=1

最後に Linux での結果:

  • が含まれていない場合、プログラムはコンパイルされません (最後に、自動的stdlib.hに含まれない 1 つのコンパイラ)。stdlibdouble -> int キャストに対してコンパイル警告は発行されません。
  • プログラムの出力は次のとおりです。x=-1.5 ax=1

ここには明確な勝者はありません。std::abs明白な答えが「好む」であることは知っていますが::abs、私は疑問に思います:

  • cplusplus.com の Web サイトは、名前空間absの外側で自動的に二重バージョンを提供する必要があると言っていますが、ここにありますか?std
  • ここでは、MSVC を除いてすべてのコンパイラとその標準ライブラリが間違っていますmath.hか (サイレントに含まれています)。
4

1 に答える 1

43

公式の参考文献によると...それは混乱です。C++11 および C11 より前:

  • 公式には、<cmath>何も導入されていません::。すべての機能が含まれていましたstd::。実際に exportは、あまり尊重されておらず、異なるコンパイラは非常に異なることをしました. を含めた場合は<cmath>、どこでも使用std:: したか、コンパイラごとに異なるものを取得しました。

  • Cはオーバーロードabsを提供しませんでした。int<stdlib.h>fabsdouble<math.h>

  • C++ に含めた場合<math.h>、何が得られたのかは明確ではありませんが、実装者の誰も標準を気にしていないようでした (上記の最初のポイントを参照)...

大まかに言えば、 を含めて<cmath>すべての用途に接頭辞を付けるかstd::、または を含めて、浮動小数点 (およびまたは以外の型のさまざまな接尾辞) のサポートが必要な場合<math.h>に使用しました。fabsintdouble

C++11 と C11 では、いくつかの新しいねじれが追加されました。

  • <cmath>もシンボルを導入できるようになりました (必須ではありません) ::。実装によって異なる可能性があるもう 1 つのこと。(ここでの目標は、既存の実装を適合させることでした。)

  • C には新しいヘッダー があり、<tgmath.h>コンパイラ マジックを使用し<math.h>て、C++ のようにオーバーロードされているかのように関数を動作させます。(したがって、 には適用されませんがabs、 にのみ適用されます。) C++ にはコンパイラ マジックが必要ないという明らかな理由から、fabsこのヘッダーは C++ には追加されていません。

全体として、状況はわずかに悪化しており、上記の私の推奨事項は依然として有効です。と のいずれか<math.h>を 含め<stdlib.h>abs/fabsとその派生語 ( labsfabsfなど) を排他的に使用するか、または を含めて排他的<cmath>に使用しますstd::abs。それ以外の場合は、移植性の問題が発生します。

于 2014-01-27T22:37:34.497 に答える