すべてのC ++演算子は何かを返しますか?


83

私が使用したすべてのC ++演算子は何かを+返します。たとえば、演算子は加算の結果を返します。

すべてのC ++演算子は何かを返しますか、それとも何も返さないC ++演算子がありますか?


7
それは、「演算子」という用語をどれだけ狭く定義するかによって異なります。
molbdnilo

12
これは標準によって強制されていません-たとえば+=、returnを実装できますがvoid、これはお勧めしません。また、関数呼び出し演算子が戻ることができvoid、これは有効です
Mircea Ispas

うーん。スコープ解決演算子::が何も返さないという予感がありますが、確認するために標準を参照する必要があります。
yksisarvinen

2
C ++で提供される型のみの質問のコンテキストですか、それともユーザー定義の型も含まれていますか?
エルジェイ

@Eljay C ++が提供する型のみ。
user8240761

回答:


111

いいえ、すべての演算子が何かを返すわけではありません。

それらはおそらくあなたが考えているものとは正確には一致しませんがdeletedelete[]C ++の「キーワード」は実際には演算子であることに注意してください。そして、それらはvoid戻り値の型を持つものとして定義されています-つまり、何も評価されません(これは「何か」ではありません)。

cppreferenceから:

void operator delete  ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;

13
私はあなたの答えが好きです、それは私に質問を異なって考えさせました。 deletedelete[]throw(void)x;キャスト、左側,演算子の右側,得演算子void?:使用する三元throw腕の1のために、dfriのoperator void()(ユーザが定義することになる)、眠りネロクさんvoid operator()()(ユーザが定義されます)。
エルジェイ

10
また、deleteオペレーターがオブジェクトを破棄してからを呼び出すことも混乱を招きますoperator deletedeleteオペレーターのエルゴとoperator deleteは別物です
Mooing Duck

7
削除演算子について話すときに、なぜ削除機能を引用するのかわかりません。しかし、何でも。
deduplicator

4
@MooingDuck削除はオブジェクトを破棄してから、を呼び出しますoperator delete
NathanOliver

削除はオペレーターとしてカウントされますか?オブジェクトは渡されたオブジェクトに作用するものだと思いましたか?削除は.....ただ、printfのような.....任意のオブジェクトは、仕事にそれを渡すか、または作成する必要はありません
Yunfei陳

82

カスタムタイプの演算子は、最も奇妙なことを行うためにオーバーロードすることができます。

たとえば、+演算子は加算の結果を返します。

必ずしも:

#include <iostream>
struct foo {
    int value = 0;
    void operator+(int x) {
        value += x;
    }
};

int main () {
    foo f;
    f + 3;
}

ここでoperator+左側をに追加しますvalueメンバーにその戻り値の型は無効です。これは作り上げられた例ですが、一般に、カスタム演算子から何かを返さないことは珍しいことではありません。

オーバーロードされる可能性があり、何かを返す必要がある唯一の演算子は、私が知っていることですが、ですoperator->。生のポインタまたはoperator->。を持つオブジェクトを返す必要があります。


おかしなことに、オーバーロードされた演算子の戻り値に実際には制約はありません。したがって、演算子は必要なものを返すことができます。en.cppreference.com/w/cpp/language/operators
bracco23

5
@ braccor23operator->は少し特殊で、operator->他の例外があるかどうかわからない、ポインタまたはオブジェクトを返す必要があります
idclev 4630358187

1
はい、それが唯一の制約です。比較演算子のブール値すらありません。それは本当に奇妙に見えます。
bracco23

9
@ idclev463035818:おそらくもっと便利な例は、式テンプレートです。たとえば、operator*(Matrix const& left, Matrix const& right)戻り値ではMatrixなく代わりMatrixMulにを返す行列ライブラリを作成できます。これにより、それがoperator+(Matrix const& left, MatrixMul const& right)操作に供給される場合、最初に乗算してから加算するよりも効率的な融合積和演算を実行できます。
Matthieu M.

1
@DarrelHoffmanとき<<とは、>>I / O操作のために、オーバーロードされている、彼らはあなたがそれらをカスケード接続することができるようにストリームを返すことが期待している:stream << foo << bar;
Barmar

34

ちょっとしたことですが、演算子は何も返しません。これらは、言語で式を作成するために使用する単なる語彙要素です。さて、式には型があり、値に評価される可能性があります。これが、「物を返す」演算子の意味だと思います。

そして、まあ、はい。タイプを持つC ++式がありますvoid(その結果、どの値にも評価されません)。明らかなものもあれば、それほど明白でないものもあります。良い例は

throw std::runtime_error()

throwC ++文法での式です。条件式など、他の式で使用できます

return goodStatus() ? getValue() : throw std::runtime_error();

そして、throw式のタイプはvoidです。明らかに、これにより実行が急速に他の場所に移動するため、式には値がありません。


21

組み込みのC ++演算子はどれも何かを返しません。オーバーロードされたC ++演算子は、演算子表記が関数呼び出しの構文糖衣である限り、何かを返します。

むしろ、演算子はすべて何かに評価します。その何かには、明確に定義されたタイプがあります。でも、関数呼び出し演算子がvoid operator()(/*params*/)あるvoidタイプ。

たとえば、+'a'はプラットフォームint'a'エンコードされた値を持つタイプです。

あなたの質問が「C ++演算子はvoid戻り値の型を持つことができますか?」である場合。答えは間違いなくイエスです。


14
@ idclev463035818:これは私が問題を抱えているリターンという用語です。C ++で何かを返すのは、関数だけです。式何かに評価されます。
バトシェバ

7
クラス型の演算子は、何かを返すメソッドです
idclev 4630358186

4
これは重要なポイントです。ずさんな用語は混乱を招きます。+1。
ピートベッカー

3
@supercat —あなたのコメントは、私を含む多くの勤勉な人々を傷つけます。標準を書いた私たちの人々は、現在または過去の他のコンパイラをポーリングすることによってコンパイラの作成者が詳細を入力することを決して期待していませんでした。この標準の目標は、C ++プログラミング言語の構文とセマンティクスを明確に定義することでした。はい、結果は完璧ではありません。最新の規格では、以前のバージョンでは対処されていなかった多くの問題が対処されています。それは、当時は単に見られなかった合併症を認識した経験から来ています。
ピートベッカー

3
@ Peter-ReinstateMonica —これがより強力なバージョンです。式I++は値を返しません。の型がiユーザー定義型の場合、その式はoperator++、値を返す関数であるとして実装されます。あなたはそれを「シンタックスシュガー」と呼んでいます。私はそれを重要な結果をもたらす区別と呼んでいます。
ピートベッカー

12

実際には、何も返さない関数呼び出し演算子を定義できます。例えば:

struct Task {
   void operator()() const;
};

17
ほとんどすべての演算子を定義して、何も返さないようにすることができます(そして、そのコードを維持する必要がある怒っている暴徒の怒りに直面します)
Yksisarvinen

7
@Yksisarvinenですが、少なくともこれは潜在的に有用です。
マークランサム

11

オペレータボイド():ユーザ定義の変換関数空隙

独自のoperator void()変換関数を定義することができます。コンパイラーは、Ttovoid変換関数が使用されないことを警告します。

#include <iostream>

struct Foo {
    operator void() { std::cout << "Foo::operator void()!"; }
    // warning: conversion function converting 'Foo' to 
    //          'void' will never be used
};
    
int main() {
    Foo f;
    (void)f;            // nothing
    f.operator void();  // Foo::operator void()!
}

[class.conv.fct] / 1によって管理されます

[...]変換関数を使用して、(おそらくcv修飾された)オブジェクトを(おそらくcv修飾された)同じオブジェクトタイプ(またはその参照)、(おそらくcv修飾された)基本クラスに変換することはありません。そのタイプ(またはそれへの参照)の、または(おそらくCV修飾) void117

117 これらの変換は、過負荷解決([over.best.ics]、[over.ics.ref])、したがって初期化([dcl.init])および明示的なキャストを目的とした標準変換と見なされます。への変換voidは、変換関数([expr.static.cast])を呼び出しません。変換を実行するために直接呼び出されることはありませんが、そのような変換関数は宣言でき、基本クラスの仮想変換関数を呼び出すことで到達できる可能性があります。

ただし、上記のように、明示的な.operator void()構文を使用して呼び出すことができます。


4

言語によって定義された(組み込みの)演算子は、さまざまな種類の計算を実行するために使用されるトークンです。

  • 算術(+、-、*、/)
  • インクリメント/デクリメント(++、-)
  • 割り当て(=、+ =、-=、* =、/ =、%=、>> =、<< =、&=、^ =、| =)
  • ロジック(!、&&、||)
  • リレーショナル(==、!=、>、<、> =、<=)
  • 条件付き?
  • コンマ

等々。リストは非常に広範囲に及ぶ可能性があります。

以下のような言語リファレンスでは、この1またはこのいずれか、これらは必ずしも単なる算術及び論理行い、何かを返すように参照されていない操作を、変数を意味することで比較が修正されてもよい、等

この演算は何らかの値をもたらすため、演算子によって「返される」と解釈される場合がありますが、関数の戻り値とは異なります。

一方、オーバーロードされた演算子は、無効になる可能性がある場合でも、何らかのタイプの戻り値で定義できます。したがって、すべての演算子がC ++で何らかの値を返すわけではありません。


3

言語の構文単位としての演算子ではなく、演算子関数について話していると思います。

任意の型で演算子をオーバーロードすると、実際には必要なものを返すことができます。

*や()のような操作は、非常に直感的に入力タイプを返さない場合があるため、これも非常に理にかなっています。複素数型と実数型を乗算することを想像してみてください。または、コレクションから要素を返す演算子。

また、++および-演算子をオーバーロードして何も返さないようにして、標準バージョンにある非常にエラーが発生しやすい副作用と式の値の混合を削除することもできます。


2

いいえ。ここで次の2つの例を検討してください。

int multiply (int a, int b) {
   return a*b;
}

void multiply_void(int a, int b) {
   cout << a*b;
//or cout << multiply(a,b);
}

最初の関数は、別の関数で使用できる整数値を返します。値が返され、必要に応じて使用できるようにメモリに保存されます。そうでなければ、それは人間には見えず、ただ幸せに記憶の中に座っています。

2番目の関数は、デフォルトの出力デバイス(通常はコンソール)に出力します。乗算演算子によって返された値は、出力デバイスに渡されます。関数multiply_voidは実際の値を返しません。


0

すべての演算子は何かを返します。それらは何かを操作するので演算子と呼ばれ、したがって何かを返します。何かを返さない演算子は、演算子とは呼ばれません。状況に応じて、何らかの値を返すか、TrueまたはFalseを返します。


0

オペレーター自身は必ずしも何も返しません。関数呼び出しは値を返します。演算子は値になります。オペレーターは関数を呼び出すことができます。例は次のとおりです。

•関数呼び出し演算子。

•関数呼び出しに変換されるオーバーロードされた演算子。

new-expressionの一部として呼び出される演算子newは、関数呼び出しです。

関数呼び出しについて言及する私の唯一の目的は、結果と戻り値を明確にすることです。[expr]で「return」の126のインスタンスすべてとそれから派生した単語を調べることに基づいています、このセクションではreturnという単語を注意深く使用して次のことを参照しているようです。

•関数呼び出しの結果

•コルーチンに関連する制御フローの側面

OK、それは結果対リターンの十分な衒学者です。


0

C ++演算子が何かを返すかどうかは、それらをどのように使用したかによって異なります。組み込みのC ++演算子は、voidを返すように強制されない限り、何らかの値を返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.