単項プラス演算子は何をしますか?私が見つけたいくつかの定義がありますが(こことここ)、それが何に使用されるのかまだわかりません。何もしないようですが、理由がありますよね?
15 に答える
実際、単項プラスは何かを行います - C でもです。オペランドに対して通常の算術変換を実行し、新しい値を返します。これは、幅の広い整数にすることができます。元の値が より小さい幅の符号なし整数であった場合int
、それも値に変更さsigned
れます。
通常、これはそれほど重要ではありませんが、影響を与える可能性があるため、整数が正であることを示す一種の「コメント」として単項プラスを使用することはお勧めできません。次の C++ プログラムを考えてみましょう。
void foo(unsigned short x)
{
std::cout << "x is an unsigned short" << std::endl;
}
void foo(int x)
{
std::cout << "x is an int" << std::endl;
}
int main()
{
unsigned short x = 5;
foo(+x);
}
これにより、「x is an int」と表示されます。
したがって、この例では、単項 plus は異なる型と符号を持つ新しい値を作成しました。
あなたが必要を感じたら、それは過負荷になるでしょう。事前定義されたすべてのタイプの場合、基本的には何もしません。
no-op単項算術演算子の実際の使用法はかなり制限されており、演算子自体ではなく、算術式で値を使用した場合の結果に関連する傾向があります。たとえば、小さい整数型からに拡張を強制したり、式の結果が右辺値として扱われ、非参照パラメーターint
と互換性がないことを確認したりするために使用できます。const
ただし、これらの使用法は、読みやすさよりもコードゴルフに適していると思います。:-)
K&R 第二版より:
単項 + は、ANSI 標準で新しく追加されました。単項 - との対称性のために追加されました。
明確にするために、負の値とは異なる正の値を強調するために使用されているのを見てきました。
shift(+1);
shift(-1);
しかし、それはかなり弱い使用法です。答えは間違いなく過負荷です。
組み込み単項+
が行うことの 1 つは、左辺値を右辺値に変換することです。たとえば、これを行うことができます
int x;
&x;
しかし、あなたはこれを行うことはできません
&+x;
:)
PS「過負荷」は間違いなく正しい答えではありません。Unary+
は C から継承されたものであり、C にはユーザーレベルの演算子のオーバーロードはありません。
unary + が達成する主なことは、int より小さいデータ型の int への型昇格です。std::cout
これは、数値データとして使用して char データを出力しようとしている場合に非常に便利です。
char x = 5;
std::cout << +x << "\n";
とは大きく異なります
char x=5;
std::cout << x << "\n";
オーバーロードにも使用できますが、実際にはオーバーロードはほぼ NOP になるはずです。
デバッグや何らかの理由で生のバイトの数値 (たとえば、char として格納された小さな数値) を出力する必要がある場合は、単項 + を使用して出力コードを簡素化できます。検討
char c = 42;
cout << c << endl; // prints "*\n", not what you want in this case
cout << (int)c << endl; // prints "42\n", ok
cout << +c << endl; // prints "42\n", much easier to type
これは簡単な例です。単項 + がバイトをテキストではなく数字のように扱うのに役立つ場合は他にもあると確信しています。
歴史的な小ネタ。C99 標準化委員会は、言語の別の機能である浮動小数点定数式の変換時の評価の抑制を実現するために単項プラスを再利用することを検討していることからも明らかなように、単項プラスの既存の使用はかなりまれであると考えていました。C Rationale のセクション F.7.4 からの次の引用を参照してください。
この仕様の初期のバージョンでは、変換時の定数演算が許可されていましたが、単項 + 演算子をオペランドに適用すると、定数式の変換時の評価を禁止する権限が与えられました。
最終的に、セマンティクスは逆転し、ほとんどのコンテキストで実行時評価が強制され (少なくとも「as if」ルールまで)、静的初期化子を使用して翻訳時の評価を強制する機能が追加されました。主な違いは、浮動小数点の例外の発生と、存在する場合はその他の浮動小数点の丸めまたは精度の設定にあることに注意してください。
あまりない。のオーバーロードを許可するための一般的な議論は、オーバーロードにoperator+()
は確かに現実世界の使用法があるということです。オーバーロードを許可するが許可しない場合operator-()
、それは非常に奇妙な(または非対称)でしょう。operator-()
operator+()
私は最初にStroustropからこの議論を読んだと思いますが、それを検証する権利を持っている本はありません。私は間違っているかもしれません。
単項プラスは C に存在し、まったく何もしませんでした (auto
キーワードのように)。それを持たないためには、Stroustrup は無償で C との非互換性を導入しなければならなかったでしょう。
C++ になると、単項マイナスのようなオーバーロード関数を許可するのが自然になりました。Stroustrup は、それがまだ存在していなければ、その理由でそれを導入した可能性があります。
だから、それは何の意味もありません。たとえば、-1.5 の反対として +1.5 を使用して、物事をより対称的に見せるための一種の装飾として使用できます。C++ では、オーバーロードできますが、operator+()
何かを行うと混乱します。標準的なルールを思い出してください: 算術演算子をオーバーロードするときは、int
s のように行います。
C がそこにある理由を探している場合は、C の初期の歴史について何かを見つけてください。C は実際には設計されていないため、正当な理由はなかったと思います。役に立たないキーワード (おそらく、現在 C++0x で再利用されているauto
とは対照的) と、何もしなかった (後に C90 で省略された) キーワードを考えてみましょう。Ritchie または Kernighan が、演算子の優先順位に問題があることに気付いたとき、壊したくない数千行のコードを含む 3 つのインストールが既にあったと述べた有名な電子メールがあります。static
entry
これについてソースを引用することはできませんが、ロスレス型変換を意味する明示的な型昇格のためであることがわかりました。つまり、変換階層の最上位に位置し、
- 昇進:
new_type operator+(old_type)
- 変換:
new_type(old_type)
- キャスト:
operator(new_type)(old_type)
- 強制:
new_type operator=(old_type)
もちろん、これは、約 15 年前に読んだマイクロソフトの (非常に古い) c/c++ マニュアルの 1 つにあるメモの私の解釈によるものです。
#include <stdio.h>
int main()
{
unsigned short x = 5;
printf ("%d\n",sizeof(+x));
printf ("%d\n",sizeof(x));
return 0;
}
上記の例に示すように、単項 + は実際に型をそれぞれサイズ 4 と 2 に変更します。+x という式が実際に sizeof で計算されるのは奇妙で、そうすべきではないと思いました。おそらくこれは、sizeof が単項 + と同じ優先順位を持つという事実によるものです。
編集私は元の答えでwaaayyyオフだったので、完全に書き直しました。
これにより、型の明示的な宣言を正の値として処理できるようになります(ほとんどの場合、非数学演算で考えられます)。否定の方が便利なようですが、違いが生じる可能性のある例を次に示します。
public struct Acceleration
{
private readonly decimal rate;
private readonly Vector vector;
public Acceleration(decimal rate, Vector vector)
{
this.vector = vector;
this.rate = rate;
}
public static Acceleration operator +(Acceleration other)
{
if (other.Vector.Z >= 0)
{
return other;
}
return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
}
public static Acceleration operator -(Acceleration other)
{
if (other.Vector.Z <= 0)
{
return other;
}
return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
}
public decimal Rate
{
get { return rate; }
}
public Vector Vector
{
get { return vector; }
}
}
常に正の数にするために使用できると思います。単項+演算子をオーバーロードしてabsにします。コードを難読化したいだけでない限り、他の開発者を混乱させる価値はありません。その後、それはうまくいくでしょう。