3

現在同じ型の引数を取るいくつかの関数について、コンパイル時に本質的に「型」情報が何であるかを追跡したいと思います。以下に例を示します。と の 2 つの関数があるgetThingIndex(uint64_t t)としgetThingAtIndex(uint64_t tidx)ます。最初の関数は、引数を のエンコーディングとして扱い、thingインデックスの重要な計算を行い、それを返します。を呼び出すことで、実際の「もの」を取得できgetThingAtIndexます。getThingAtIndex一方、構造を照会していて、既にインデックスがあると想定しています。2 つの方法のうち後者の方が高速ですが、より重要なことは、 to を渡すこと、またはthingtoを渡すことによって生じる頭痛を避けたいということです。getThingAtIndexindexgetThingIndex

thing私は次のような種類のインデックスを作成することを考えていました:

struct Thing { uint64_t thing; }
struct ThingIndex { uint64_t idx; }

そして、上記の関数のシグネチャを次のように変更します

getThingIndex(Thing t)
getThingAtIndex(ThingIndex idx)

現在、と が同じ基になる型Thingをエンコードしているにもかかわらず、それらはコンパイル時に区別されるため、 にインデックスまたはものをThingIndex渡すことで愚かな間違いを犯す機会が少なくなり ます。getThingIndexgetThingAtIndex

ただし、このアプローチのオーバーヘッドが心配です。関数は何回も (数千万回から数億回) 呼び出されますが、基本的にコンパイル時の型情報をエンコードするだけのこれらの構造の作成をコンパイラが最適化して排除するかどうかに興味があります。コンパイラがそのような最適化を実行しない場合、これらのタイプの「豊富なタイプ」をオーバーヘッドなしで作成する方法はありますか?

4

1 に答える 1

5

解体の様子をご覧ください。

unsigned long long * x = new unsigned long long;
0110784E  push        8  
01107850  call        operator new (01102E51h)  
01107855  add         esp,4  
01107858  mov         dword ptr [ebp-0D4h],eax  
0110785E  mov         eax,dword ptr [ebp-0D4h]  
01107864  mov         dword ptr [x],eax  
*x = 5;
01107867  mov         eax,dword ptr [x]  
0110786A  mov         dword ptr [eax],5  
01107870  mov         dword ptr [eax+4],0  

そして構造体。

struct Thing { unsigned long long a; };
Thing * thing = new Thing;
0133784E  push        8  
01337850  call        operator new (01332E51h)  
01337855  add         esp,4  
01337858  mov         dword ptr [ebp-0D4h],eax  
0133785E  mov         eax,dword ptr [ebp-0D4h]  
01337864  mov         dword ptr [thing],eax  
thing->a = 5;
01337867  mov         eax,dword ptr [thing]  
0133786A  mov         dword ptr [eax],5  
01337870  mov         dword ptr [eax+4],0  

2 つの命令に違いはありません。コンパイラはthis->aそれが構造体のメンバーであることを気にせず、宣言したばかりであるかのようにそれにアクセスしますunsigned long long a

于 2013-03-28T19:04:33.240 に答える