1. ホーム
  2. c++

[解決済み] なぜstring::compareはintを返すのですか?

2022-12-28 20:30:45

質問

なぜ string::compare int のような小さな型ではなく short または char ? 私の理解では、このメソッドは-1、0、または1のみを返します。

2番目の部分ですが、もし私が型 Foo で、-1、0、1 のいずれかを返すだけだとしたら、このメソッドで short あるいは char が一般的に良いアイデアでしょうか?

編集部:訂正しました。 string::compare は-1, 0, 1を返しません。実際には、0, <0, 0という値を返します。

答えはおおよそ、より小さい型を返す理由はないようです。 int なぜなら、戻り値は "rvalues" であり、それらの "rvalues" は int 型 (4 バイト) より小さいことから利益を得られないからです。また、多くの人が、ほとんどのシステムのレジスタはおそらくサイズ int のサイズであることを多くの人が指摘しました。これらのレジスタは、1、2、または 4 バイトの値を与えても満たされるため、より小さい値を返すことに実際の利点はありません。

編集2: 実際、アライメントやマスクなど、より小さなデータ型を使用する際に余分な処理オーバーヘッドが発生する可能性があるように見えます。一般的なコンセンサスは、配列の場合のように、多くのデータを扱うときにメモリを節約するために、より小さいデータ型が存在するということです。

今日何かを学びました、みんな本当にありがとう

どのように解決するのですか?

まず、仕様としては、以下の値を返すということです。 よりも小さいか、等しいか、大きい値を返します。 0 であり、必ずしも -1 または 1 . 次に,返り値はrvalueで,積分促進が適用されます。 であるため、これより小さいものを返す意味はありません。

C++では(Cと同様に)、すべての式はrvalueかlvalueです。 lvalue のいずれかです。 歴史的に、この用語は lvalue が代入の左側に現れるという事実を参照しています。 が代入の左側に現れるのに対し、rvalue は右側にしか現れないという事実を指しています。 は右側にしか現れません。 現在では、非クラス型では単純に 今日、非クラス型では、l値はメモリ上にアドレスを持ち、r値は持たないという単純な近似値になっています。 rvalueはそうではありません。 したがって,rvalueのアドレスを取得することはできません. したがって、rvalueのアドレスを取ることはできず、cv-qualifiers(条件 "access")は適用されないのです。 C++の用語では C++の用語では、クラス型を持たないrvalueは純粋な値であり、オブジェクトではありません。 値であり、オブジェクトではありません。 関数の戻り値は、参照型を持たない限り 関数の戻り値は、それが参照型を持たない限り、rvalueです。 (レジスタに収まる非クラス型は レジスタに適合する非クラス型は、ほとんどの場合レジスタで返されます。 例えばレジスタに収まる非クラス型は、メモリ内ではなくレジスタで返されることがほとんどです)。

クラス型については、問題はもう少し複雑です。 という事実があります。 ができます。 でメンバ関数を呼び出すことができるためです。 これは は、rvalue が実際にアドレスを持っていなければならないことを意味します。 this ポインタのために,rvalue は実際にアドレスを持っていなければならず,また,cv-qualification がオーバーロードの解決の役割を果たすので,cv-qualification であることが可能です. はオーバーロードの解決に一役買っているからです。 最後に、C++11 では、次のような新しい区別が導入されています。 最後に、C++11 では、rvalue 参照をサポートするために、いくつかの新しい区別が導入されています。 これらも主にクラス型に適用されます。

積分促進とは、積分型が よりも小さい int よりも小さい整数型が式のr値として使われる場合、ほとんどの文脈で、それらは に昇格します。 int . ですから,たとえ と宣言された変数があったとしても short a, b; と宣言されていても、式の中では a + b という表現がありますが、どちらも ab に昇格します。 int に昇格します。 に昇格する。 同様に、もし私が a < 0 と書くと、比較は の値で比較されます。 a に変換され int . 実際には が違いになるケースは非常に少ないです。 2 の補数で整数演算がラップされるようなマシン(つまり、ごく少数のエキゾチックなマシンを除いて、今日では Unisysのメインフレームが唯一の例外だと思います。 メインフレームが唯一の例外だと思います)。 それでも、より一般的なマシンでさえ より一般的なマシンでも

short a = 1;
std::cout << sizeof( a ) << std::endl;
std::cout << sizeof( a + 0 ) << std::endl;

は異なる結果を与えるはずです。 sizeof( short ) と等価であり、2番目の sizeof( int ) (となります。 になります(統合プロモーションのため)。

この2つの問題は形式的に直交しており、rvaluesとlvaluesは は積分プロモーションとは関係ありません。 ただし ... integral promotion は rvalue にのみ適用され、rvalue を使用するほとんどの場合(全てではありませんが)は rvalueを使用する場合のほとんど(全てではありません)で、integral promotionが発生します。 になります。 このため よりも小さい値で数値を返す理由はありません。 int . として返してはいけないという非常に良い理由もあります。 を文字型として返してはいけないという非常に正当な理由があります。 オーバーロードされた演算子、例えば << のように、オーバーロードされた演算子はしばしば のようなオーバーロードされた演算子は文字型に対して異なる振る舞いをします。 を文字型としてのみ返すようにしたい。 (以下のように比較できます。 という違いがあります。

char f() { return 'a'; }
std::cout << f() << std::endl;      //  displays "a"
std::cout << f() + 0 << std::endl;  //  displays "97" on my machine

この違いは、2番目のケースでは、加算によって によって積分促進が起こり、その結果、異なる のオーバーロードになります。 << が選択されることです。