単項プラス演算子は何をしますか?


86

単項プラス演算子は何をしますか?私が見つけたいくつかの定義がありますが(ここここ)、それが何に使用されるのかまだわかりません。何もしないようですが、理由がありますよね?


3
歴史的な理由はひどく過小評価されていると思います。
ウルフ

3
3つの異なる言語タグを使用した質問は非常にあいまい/悪いです!答えは、C#(オーバーロード可能)とC(オーバーロードなし)およびC ++(オーバーロード可能ですが、これをCから継承し、したがってそのプロパティも継承します)では大きく異なります。
legends2k 2015

Eric LippertのC#のトップ10の欠陥へのリンクを追加したいと思います。単項プラス演算子は、名誉ある言及にあります。informit.com / articles / article.aspx?p = 2425867彼は基本的に、削除する必要があるか、追加してはいけないと言っています。
ノエルウィドマー

回答:


57

あなたが必要を感じたら、それは過負荷になるはずです。事前定義されたすべてのタイプの場合、基本的には何もしません。

no-op単項算術演算子の実際の使用法はかなり制限されており、演算子自体ではなく、算術式で値を使用した場合の結果に関連する傾向があります。たとえば、小さい整数型からに拡張を強制しintたり、式の結果が右辺値として扱われるため、非const参照パラメーターと互換性がないことを確認したりするために使用できます。ただし、これらの使用法は、読みやすさよりもコードゴルフに適していると思います。:-)


7
以下のいくつかの例が示すように、これは実際には真実ではありません。
jkerian 2010年

3
さて、私はそれがいくつかの用途を持っていることを購入しますが、以下で説明する用途のほとんどは、それがno-op演算子を使用して構築された数値式であるという事実に関連しています:たとえば、昇格intして右辺値を生成するのは式の効果です+演算子自体ではなく、-ness。
ジェフリーハンティン2010年

118

実際、単項プラス、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はintです」と表示されます。

したがって、この例では、単項プラスは、異なるタイプ符号付きの新しい値を作成しました。


5
等しいと比較するshortとintが与えられたときに与えられた結果を生成するコードを書いている場合、おそらく別の問題があります
Lie Ryan

1
おかげで、それは明確になります(補足:Cでは、foo関数をオーバーロードできないため、例を機能させることができませんでした)
Binarian 2013

とはどういう意味an integer of greater widthですか?
yekanchi

このコンテキストでは、「幅」は値に関連付けられたストレージのバイト数を指します。
ジャイルズ

41

K&R第2版から:

単項+は、ANSI規格の新機能です。単項-との対称性のために追加されました。


6
絶対に。*これは歴史的な理由です。C ++はそれを適応させる必要があったため、オーバーロードに対処する必要がありました。
ウルフ

37

明確にするために、負の値とは異なる正の値を強調するために使用されているのを見てきました。

shift(+1);
shift(-1);

しかし、それはかなり弱い使用法です。答えは間違いなく過負荷です。


8
特に次のようなベクトルを扱う場合は、これも行いましたvec3(+1,-1,-1)
mpen

28

組み込みの単項演算+が行うことの1つは、左辺値を右辺値に変換することです。たとえば、これを行うことができます

int x;
&x;

しかし、あなたはこれを行うことはできません

&+x;

:)

PSの「オーバーロード」は間違いなく正しい答えではありません。単項+演算はCから継承されており、Cではユーザーレベルの演算子のオーバーロードはありません。


14

unary +が達成する主なことは、intよりも小さいデータ型のintへの型昇格です。これはstd::cout、数値データとして使用してcharデータを出力しようとしている場合に非常に役立ちます。

char x = 5;
std::cout << +x << "\n";

とは大きく異なります

char x=5;
std::cout << x << "\n";

オーバーロードにも使用できますが、実際にはオーバーロードほぼNOPである必要があります。


12

デバッグなどの理由で生のバイトの数値(たとえば、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

これは簡単な例です。単項+が、バイトをテキストではなく数値のように扱うのに役立つ場合もあると思います。


4

歴史的な一口。C99標準化委員会はまた、単項プラスの既存の使用はかなりまれであると考えました。これは、単項プラスを再利用して言語の別の機能を実現することを検討していることからも明らかです。浮動小数点定数式の翻訳時間評価の禁止です。Cの理論的根拠のセクションF.7.4からの次の引用を参照してください。

この仕様の初期のバージョンでは、変換時定数の算術演算が可能でしたが、オペランドに適用すると、単項+演算子を使用して、定数式の変換時評価を禁止することができました。

結局、セマンティクスは逆になり、ほとんどのコンテキストで実行時評価が実施され(少なくとも「あたかも」ルールまで)、静的初期化子を使用して変換時評価を実施できるようになりました。主な違いは、浮動小数点例外の発生、およびその他の浮動小数点の丸めまたは精度設定(存在する場合)にあることに注意してください。


3

あまりない。のオーバーロードを許可するための一般的な議論は、オーバーロードにoperator+()は確かに現実の使用法があるということです。オーバーロードを許可するが許可しない場合operator-()、それは非常に奇妙な(または非対称)でしょう。operator-()operator+()

私は最初にStroustropからこの議論を読んだと思いますが、それを検証する権利を持っている本はありません。私は間違っているかもしれません。


3

単項プラスはCに存在し、まったく何もしませんでした(autoキーワードのように)。それを持たないために、StroustrupはCとの不必要な非互換性を導入しなければならなかったでしょう。

C ++になると、単項マイナスのようにオーバーロード関数を許可するのが自然でした。Stroustrupがまだ存在していなかった場合は、その理由でそれを導入した可能性があります。

だから、それは何の意味もありません。これは、物事をより対称的に見せるための一種の装飾として使用できます。たとえば、-1.5の反対として+1.5を使用します。C ++では、オーバーロードされる可能性がありますが、operator+()何かを行うと混乱します。標準の規則を覚えておいてintください。算術演算子をオーバーロードするときは、sのように実行してください。

それがそこにある理由を探しているなら、Cの初期の歴史について何かを見つけてください。Cは実際には設計されていなかったので、正当な理由はなかったと思います。役に立たないautoキーワード(おそらくstatic、現在C ++ 0xでリサイクルされているのとは対照的)と、entry何もしなかった(後でC90で省略された)キーワードについて考えてみます。RitchieまたはKernighanが、オペレーターの優先順位に問題があることに気付いたとき、壊れたくない数千行のコードを含む3つのインストールがすでにあったと言っている有名な電子メールがあります。


1
私が見た、意味のある非算術過負荷は、正規表現または文法でのみでした。ここで、(+ term)は1つ以上の用語を意味します。(これはかなり標準的な正規表現構文です)
Michael Anderson

についてentry:(stackoverflow.com/q/254395/153285)。最近では、複数のエントリポイントが必要な場合は、末尾呼び出しとプロファイルに基づく最適化を使用するだけです。
ポテトスワッター2010年

与えられたC99でもextern volatile int foo;、ステートメント+foo;を与えられたコンパイラは、読み取りが行われたことを決定するための手段が存在すると考えられるプラットフォームで、示されたアドレスの読み取りを実行する必要があると思います。多くのコンパイラが礼儀としてそれを行うでしょうが、ステートメントが単に「foo」である場合にそれが必要になるかどうかはわかりません。
スーパーキャット2015

2

これについては何の出典も引用できませんが、明示的な型昇格のためであり、ロスレス型変換を意味することがわかりました。これにより、コンバージョン階層の最上位になります。

  • プロモーション: new_type operator+(old_type)
  • 変換: new_type(old_type)
  • キャスト: operator(new_type)(old_type)
  • 強制: new_type operator=(old_type)

もちろん、それは私が約15年前に読んだマイクロソフト(本当に古い)c / c ++マニュアルの1つにあるメモの私の解釈からのものなので、一粒の塩でそれを取ってください。


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が単項+と同じ優先順位を持っているという事実が原因です。


-1

常に正の数にするために使用できると思います。単項+演算子をオーバーロードしてabsにします。コードを難読化したいだけでない限り、他の開発者を混乱させる価値はありません。その後、それはうまくいくでしょう。


それは、単項マイナスを負の腹筋にオーバーロードしない限り、混乱する単項マイナスの反対ではありません。これにより、あらゆる種類の数学が奇妙になります
Davy8

ええと、ええ。そういうわけで私はそれをしないことを提案した。
パトリック

1
@ Davy8:単項プラスが現在、単項マイナスの「反対」であるとあなたが思う理由は何ですか?ビット単位の補数演算子の「反対」とは何~ですか?あなたの「反対」の定義が何であるかはわかりませんが、単項プラスと単項マイナスが現在行っていることの経験によってバイアスがかかっているのではないかと思います。
ndkrempel 2012

-1

編集私は元の答えで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; }
    }
}

それは私には単項演算のようには見えません。2つの引数(4月と5月)が必要なので、バイナリになります。
BlueMonkMN 2009

それはバイナリプラスです。単項プラスは単に「+1」などであり、左オペランドはありません。
ジェフリーハンティン2009

私の悪い。CS101を忘れてしまいました。修繕。
Michael Meadows

3
本番コードでそのような過負荷を見つけた場合は、間違いなくバグとしてマークし、できるだけ早く修正します。のセマンティクスは+、値を正にすることではなく、その符号を変更しないことです。
アルトゥーロ・トレス・サンチェス

-1

単に、どの数値が正であるかを納得させるために使用されたもの

例えば;

int a=10;
System.out.println(+x);// prints 10(that means,that number 10 multiply by +1,{10*+1})

//if we use unary minus

int a=10;
System.out.println(-x);//prints -10(that means,that number 10 multiply by +1,{10*-1})
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.