LoginSignup
1
2

More than 5 years have passed since last update.

ポインター間のstatic_castの実行時コスト

Last updated at Posted at 2016-10-22

結論

一般にnullptrチェックのコストがかかると思われます.

なお,この記事では,アドレス値のコピーのコストについては議論しません.

詳細

C++において,ポインター間のstatic_castを行った場合,コンパイラーによって,必要なアドレスのオフセット値が算出され,その値をアドレスに加算するコードが生成されます.Cだとオフセット値を算出して加算するコードを明示的に書かないといけません(もちろん,ちょっとしたマクロを書けばタイプ量を減らすことは可能です).

C++のstatic_castはとても便利なのですが,仕様上nullptrはキャストしてもnullptrとなるため,単純にアドレスにオフセット値を加算するわけにはいきません.

例えば,以下のようなポインター間のstatic_castを行った場合,

test.cc
// 単一継承の場合や,Bがメンバ変数を持っていない場合(多分コンパイラー依存)などは,
// static_castのnullptrチェックは発生しないと推測されるので,ここでは扱わない
class A { int a; };
class B { int b; };
class C : public A, public B {};

int main() {
  C c;
  B* b = static_cast<B*>(&c);
  return 0;
}

以下のようなコードが生成されます.

$ clang++ -std=c++11 -S -emit-llvm test.cc  # 最適化オブションなし
test.llからの抜粋
; Function Attrs: norecurse nounwind uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  %c = alloca %class.C, align 4
  %b = alloca %class.B*, align 8
  store i32 0, i32* %1, align 4
  %2 = icmp eq %class.C* %c, null
  br i1 %2, label %7, label %3

; <label>:3                                       ; preds = %0
  %4 = bitcast %class.C* %c to i8*
  %5 = getelementptr inbounds i8, i8* %4, i64 4
  %6 = bitcast i8* %5 to %class.B*
  br label %7

; <label>:7                                       ; preds = %3, %0
  %8 = phi %class.B* [ %6, %3 ], [ null, %0 ]
  store %class.B* %8, %class.B** %b, align 8
  ret i32 0
}

アドレスに対してオフセット値を加算する前に,nullとの比較を行っていることがわかります.

最適化によって,確実にnullptrではない場合は,nullptrチェックを行わずアドレスにオフセット値を加算するコードを生成する場合があります.しかし,一般的にはnullptrかどうかは実行時に判定する必要があります(動的リンクされる共有ライブラリに含まれる関数・メソッドを呼び出す場合を考えるとよいかもしれません).そのため,仮に関数・メソッドの事後条件でnullptrでないことが保証されていたとしても,nullptrチェックがstatic_castの実行時コストとしてかかるものと考えられます.

あまり深く考えたわけではないため,間違っているかもしれませんが,多分static_castのnullptrチェックを強制的になくすようなコードを書くことはできないものと思います.もちろん,reinterpret_castを使い,オフセット値の加算を明示的に書けば,Cのようにnullptrチェックをなくせるでしょう.

1
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2