11

持つ

struct Person {
   string name;
};

Person* p = ...

オーバーロードされた演算子はないと仮定します。


どちらがより効率的ですか (もしあれば)?

(*p).name 対。 p->name

頭の後ろのどこかで、*逆参照演算子がオブジェクトの一時的なコピーを作成する可能性があるというベルが鳴っているのが聞こえます。これは本当ですか?


この質問の背景には、次のようなケースがあります。

Person& Person::someFunction(){
    ...
    return *this;
}

Person*そして、結果を に変更し、最後の行を に変更するだけreturn thisで (パフォーマンスに) 違いが生じるのではないかと考え始めました。

4

4 に答える 4

9

違いはありません。標準でさえ、2つは同等であると述べており、両方のバージョンで同じバイナリを生成しないコンパイラがある場合、それは悪いものです.

于 2013-05-03T09:21:19.840 に答える
8

参照を返すとき、それはポインタを返すのとまったく同じです。ポインタのセマンティクスは除外されます。ではなく要素
を返します。sizeof(void*)sizeof(yourClass)

だからあなたがそれをするとき:

Person& Person::someFunction(){
    ...
    return *this;
}

参照を返しますが、その参照の固有のサイズはポインターと同じであるため、実行時の違いはありません。

の使用についても同じことが言えます(*i).nameが、その場合は参照と同じセマンティクスを持つl-valueを作成します (こちらも参照)

于 2013-05-03T09:26:22.777 に答える
2

はい、読むのも入力するのもはるかに難しいので、よりも を使用した方がはるかに優れていますがx->y(*x).y入力の効率を除けば、まったく違いはありません。コンパイラは、いずれかの形式を使用するかどうかにかかわらず、 の値を読み取り、xオフセットを に追加する必要があります [もちろん、 and をそれぞれyオーバーライドする面白いオブジェクト/クラスが含まれていないと仮定して]operator->operator*

が参照されたときに余分なオブジェクトが作成されることは絶対にありません(*x)。ポインターの値は、プロセッサーのレジスターにロードされます [1]。それでおしまい。

参照を返すと、オブジェクトのコピーを作成するのではなく、オブジェクトへのポインター (変装して) を返すため、通常はより効率的です。ポインターのサイズよりも大きいオブジェクトの場合、これは通常有利です。

[1] はい、レジスタを持たないプロセッサ用の C++ コンパイラを使用できます。1984年頃に見たRank-Xeroxのプロセッサを少なくとも1つ知っています。これにはレジスタがなく、専用のLiSPプロセッサであり、LiSPオブジェクト用のスタックしかありません...しかし、それらは一般的ではありません今日の世界では。レジスタを持たないプロセッサで作業している人がいる場合は、そのオプションについて説明していないという理由だけで、私の回答に反対票を投じないでください。答えをシンプルにしようとしています。

于 2013-05-03T09:35:30.057 に答える
1

Any good compiler will produce the same results. You can answer this yourself, compile both codes to assembler and check the produced code.

于 2013-05-03T09:22:51.757 に答える