0

私たちは皆、->vsについて知っています。c / c ++でメンバーにアクセスするための速度の差分ですが、単純なドット演算子の実際のコストの手がかりを見つけるのは難しいです。

address-of-struct + offsetのようなものを想像します。また、offsetは、先行するすべてのメンバーのすべてのsizeof-sの合計であると想定します。これは(大まかに)正しいですか?

それでは、->誰と比べてはるかに速いのでしょうか?二度?
(ここSOでいくつかのasmを見たことがありますが、アクセスは1つの命令であり、魔法があると思います)

また、ローカル変数と比較して、どれくらい遅いですか?

ありがとうございました

編集:
私はそれを正しく尋ねることができなかったと思います。

物事を片付けようとするには:
「->vs。」「ポインタを使用して構造体にアクセスする」と「メンバーに直接アクセスする」という意味でした-(リンク)。
そして、私はただ興味がありました。「わかりました。ドットアクセス自体はどうですか?それは酸っぱいコストがかかります。」それで私は質問をしました。

「ドット演算子のコストc/c ++」自体は、ばかげた/ナンセンス/ナイーブな質問かもしれませんが、それでも私が探していた答えは得られます。今はそれを上手く言うことはできません。

ありがとう

4

4 に答える 4

8

-> vs については誰もが知っています。c/c++ でメンバーにアクセスするための高速差分ですが、単純なドット演算子の実際のコストの手がかりを見つけるのは困難です。

「私たち全員」にはどうやら私は含まれていません。と->. ._

address-of-struct + offset のようなものだと思います。また、オフセットが先行するすべてのメンバーのすべての sizeof-s の合計であると仮定します。これは(おおよそ)正しいですか?

はい。

->では、どれくらい速いかを比べて?二回?(ここSOで、アクセスが1つの命令であるというasmを見たこと.がありますが、それにはいくつかの魔法があると思います)

と の両方->.実効アドレスの計算が含まれ、これが最もコストのかかる操作です (実際のメモリ アクセス以外に)。ポインター ( の左側->) が非常に頻繁に使用される場合 (例this)、コンパイラーによって CPU レジスターに既にキャッシュされている可能性が高く、 と の間の違いを効果的に無効に->.ます。

はポインタでthisあり、メソッド内のオブジェクトに属するものはすべて実質的に のプレフィックスが付いてthis->いますが、C++ プログラムは速度を落としていません。

明らかに、.を参照に適用すると、 と 100% 同等です->

また、ローカル変数と比較してどれくらい遅いですか?

評価しにくい。メタ アセンブラの基本的な違いは次のとおりです。ローカル変数にアクセスするための 2 つの asm ops (スタック上の変数のオフセットをスタック ポインターに追加し、値にアクセスする) と、ポインターを介してオブジェクトの属性にアクセスするための 3 つの asm ops (loadオブジェクトへのポインター、オフセットの追加、値へのアクセス)。ただし、コンパイラの最適化により、違いはほとんど目立ちません。

多くの場合、際立っているのはローカル変数とグローバル変数の違いです。ローカル変数/オブジェクトの属性のアドレスを計算する必要がありますが、すべてのグローバル変数にはリンク時に計算された一意のグローバル アドレスがあります。

しかし、フィールド/属性アクセスのオーバーヘッドは、たとえばシステム コールのオーバーヘッドと比較すると、ごくわずかであり、ごくわずかです。

于 2010-08-09T13:05:18.980 に答える
5

まともなコンパイラはstructコンパイル時にフィールドのアドレスを計算するので、コストは. ゼロになるはずです。

つまり、使用するstructフィールドへの.アクセスは、変数へのアクセスと同じくらいコストがかかります。

于 2010-08-09T12:23:50.947 に答える
0

I would say the difference of cost isn't in the operators themselves, but in the cost of accessing the left-side object.

ptr->variable

should produce a similar asm output than

(*ptr).variable // yeah I am using a '.' because it's faster...

therefore your question is kind of nonsensical as it is.

I think I understand what you meant though, so I'll try to answer that instead.

The operators themselves are nearly costless. They only involve computing an address. This address is expressed as the address of the object plus an offset (likely fixed at compile time and therefore a constant in the program for each field). The real cost comes from actually fetching the bytes at this address.

Now, I don't understand why it would be more costly to use a -> vs a . since they effectively do the same thing, there can be a difference of access though in this case:

struct A { int x; };

void function(A& external)
{
  A local;

  external.x = local.x;
}

In this case, accessing external.x is likely to be more costly because it necessitates accessing memory outside of the scope of the function and therefore the compiler cannot know in advance whether or not the memory will have already been fetched and put in the processor cache (or a register) etc...

On the other hand local.x being local and stored on the stack (or a register), the compiler may optimize away the fetch part of the code and access local.x directly.

But as you notice there is no difference between using -> vs ., the difference is in using a local variable (stored on the stack) vs using a pointer / reference to an externally supplied object, on which the compiler cannot make an assumption.

Finally, it's important to note that if the function was inlined, then the compiler could optimize its use at the caller's site and effectively use a slightly different implementation there, but don't try to inline everything anyway: first of all the compiler will probably ignore your hints, and if you really force it you may actually lose performance.

于 2010-08-09T13:45:33.610 に答える
0

それは膨大な数のことに依存します。

演算子は.、ローカル変数にアクセスしたり、使用->したりするよりも安価なものから、どちらかよりもはるかに高価なものまでさまざまです。

これは賢明な質問ではありません。

于 2010-08-09T12:25:25.267 に答える