30

単項演算子は、単項演算+子との対称性のためにのみ含まれていました-か、それともC ++コードで実用的ですか?

ここを検索して、Cの単項'+'演算子の目的は何ですか?、しかし、そこにある唯一の有用なシナリオは、プリプロセッサマクロを含みます。それらは知っておくとよいですが、あまり一般的ではない状況のようで、マクロが関係しています。より一般的なC++コードを含むユースケースはありますか?

4

9 に答える 9

33
char ch = 'a';
std::cout << ch << '\n';
std::cout << +ch << '\n';

最初の挿入により、文字aがに書き込まれcoutます。2番目の挿入は、の数値をに書き込みchますcout。しかし、それは少しあいまいです。+これは、コンパイラーがオペレーターに統合プロモーションを適用することに依存しています。

于 2013-01-16T19:07:27.043 に答える
21

単項-との対称性は完全に役に立たないわけではありません。強調に使用できます。

const int foo = -1;
const int bar = +1;

また、オーバーロードされた単項演算を使用して、自明ではない計算を実行しながら、オペランドと同じ論理+値を生成する演算を示すことができます。(これは、単項変換ではなく単項変換をオーバーロードできるAdaの型変換で行われるのを見てきました。)C ++の良い例がないので、スタイルが悪いと主張する人もいるかもしれません。(それから、私はオーバーロードについてたくさんの怒りを見てきました。)+<<

C ++がそれを持っている理由に関しては、それはおそらく主にCとの一貫性のためであり、1989年のANSI規格でそれを追加しました。Cの理論的根拠は次のように述べています。

単項プラスは、単項マイナスとの対称性のために、いくつかの実装からC89委員会によって採用されました。

于 2013-01-16T19:07:41.400 に答える
11

クラスの数値のセマンティクスを明示的に避けている場合、演算子のオーバーロードは「intのように行わない」ことは明らかです。その場合、単項プラスは意味を持ち、単に戻るだけではありません。*this

顕著な例:埋め込まれたEBNFのKleene Plusに対するBoost.Spiritの単項プラスは、引数(パーサールールも)を1回以上一致させるパーサールールを生成します。

于 2013-01-16T19:17:25.070 に答える
5

単項+演算子は、左辺値を右辺値に変換します。

struct A {
  static const int value = 1;
};

// ...

int x = std::min(0, A::value);

ああ、いや!誰かが定義(および宣言)するのを忘れたため、このコードはリンクされませんA::valuestd::min引数を参照A::valueで受け取るため、参照がそれにバインドできるようにアドレスが必要です(技術的には、1つの定義規則では、プログラムで1回だけ定義する必要があります)。

気にしないでください、救助への単項プラス:

int x = std::min(0, +A::value);

単項プラスは同じ値の一時を作成し、参照は一時にバインドされるため、欠落している定義を回避できます。

これは頻繁に必要なものではありませんが、単項プラス演算子の実用的な使用法です。

于 2013-03-05T23:25:08.577 に答える
3

単項+は統合プロモーションを適用します。@PeteBeckerの回答は、役立つ1つの方法を示しています。

もう1つは、スコープなしの列挙型が、内のすべての値を表すことができる整数型にプロモートされることに注意してくださいenum。したがって、C ++ 03では、C ++ 11がなくても、次のstd::underlying_type<T>ことができます。

enum MyBitMask {
    Flag1 = 0x1,
    Flag2 = 0x2,
    Flag3 = 0x4,
    Flag4 = 0x8000000
};

inline MyBitMask operator&(MyBitMask x, MyBitMask y) {
    return static_cast<MyBitMask>( +x & +y );
}

inline MyBitMask operator|(MyBitMask x, MyBitMask y) {
    return static_cast<MyBitMask>( +x | +y );
}
于 2013-01-18T22:04:00.307 に答える
1

少し遅れましたが、これは私が偶然見つけた非常にねじれた使用法です。どうやら、この+演算子は、空のプリプロセッサトークンに遭遇する可能性を回避するためのセーフガードを設計するときに(おそらく厳密には必要ではないにしても)役立つ可能性があります。より詳細な議論については、この投稿を参照してください。

それは実用的ですが、決して楽しいものではありません。

于 2014-01-20T01:30:52.697 に答える
1

特に、+ラムダを関数ポインターに変換します。通常、変換は自動的に行われますが、そうでない場合もあります。

たとえば、これはコンパイルされません。

std::array arr{
    [](int x){return x*x;},
    [](int x){return x*x*x;},
};

std::arrayテンプレートパラメータとして関数ポインタ型を指定することで機能させることも、次のようにすることできます。

std::array arr{
    +[](int x){return x*x;},
    +[](int x){return x*x*x;},
};
于 2020-08-30T11:10:16.457 に答える
0

算術変数の場合、operator+は新しい値を生成するためです。これを使用して、参照のような(プロキシ)タイプの値のコピーを生成します。

template<class T> class ref_of{
   T* impl_; // or a more complicated implementation
public:
   T operator+() const{return *impl_;}
   operator T&()&{return *impl_;}
}

別のオプションを使用するoperator*ことref_ofもできますが、ポインターのようなオブジェクトと混同される可能性があります。

于 2020-08-30T10:57:50.923 に答える
0

算術変数の場合、operator +は新しい値を生成するため、一般に、参照のような(プロキシ)タイプの値のコピーを生成するために使用します。

template<class T> class ref_of{
   T* impl_; // or a more complicated implementation
public:
   T operator+() const{return *impl_;} 
   operator T&()&{return *impl_;}
}
...
ref_of<T> r = t;
auto s = +r; // this forces a copy

別のオプションを使用するoperator*ことref_ofもできますが、ポインターのようなオブジェクトと混同される可能性があります。

于 2020-08-30T12:06:23.920 に答える