4

私は、標準アルゴリズムの不器用な独自のバージョンを再実装することを避けようとしているため、標準ライブラリ バージョンで遊んでいます。私は C++ の専門家ではないので、慎重に進め、完全なデバッグ オプションをオンにします。

valarray具体的には、コンテナーでバイナリ検索を使用しています。次のコード ブロックは正しい結果を生成するようであり、問​​題はありvalgrindません。それでも、自分のやっていることが本当に許可されているのか、それとも単にコンパイラによって許可されているのかがわからないので、滑りやすい坂道を進んでいると感じています。

代表的なコード:

#include <iostream>
#include <valarray>
#include <algorithm>
#include <typeinfo>

using namespace std;

int main(){

 valarray<double> v(10);
 for (int i=0 ; i<10 ; ++i){
   v[i]=2. *i ; 
   cout<<v[i]<<"  ";
 }
 cout << "\n";

 double what=17;
 double* it=lower_bound(&v[0], &v[10],what) ; 

 cout<<it-&v[0]<<" "<<typeid(&v[0]).name()<<" ";
 cout<<typeid(it).name()<<" "<<typeid(it-&v[0]).name()<<"\n"; // ???

 int idx=it-&v[0];
 cout<<"v["<<idx<<"]="<<v[idx]<<"\n";
}

質問:

  1. 私がここでしていることは本当に合法ですか?
  2. double への 2 つのポインターの差が int になるのはなぜですか? (???コメントの行で)
  3. 型変換のオーバーヘッドはどのくらいですか? ---この種の機能は、計算時間の 90% 以上を占めるコードの一部に配置されるため、効率に関心があります
4

3 に答える 3

2
  1. intにインデックスを付けるためにを使用していvalarrayます。これは例では有効ですが、一般的には有効ではありません。std::size_tにインデックスを付けるには、 を使用しますvalarray。(std::vector通常の配列も同様です。)

  2. 任意の型への 2 つのポインターの違いは、指定されていない整数型でintありlongstd::ptrdiff_t.

  3. どの変換?

于 2011-03-09T01:14:07.727 に答える
1

これはすべて定義された動作であり、どの実装でも引き続き機能すると思います。valarrayのさまざまなドキュメントを見ると、他のすべてのこと::std::valarrayが当てはまるためには合法である必要があるようです。resize要素へのベアポインタは、メンバー関数が呼び出されるか、valarrayが破棄されるまで完全に有効なままである必要があります。

valarray唯一の本当の問題は、その要素を連続して保持する必要があるかどうかです。そして、私はその質問に対する答えを投稿で見つけました。ここから抜粋します。

はい、valarrayも連続したストレージを使用します。標準の具体的な表現は($ 26.3.2.3 / 3)です。式&a [i + j] ==&a [i] + jは、i+jが非定数配列の長さa。

もちろん、スライスイテレータの作成はそれほど難しくないはずですが、スライスを標準のアルゴリズムで直接使用することはできません。双方向のものを作成するのは非常に簡単ですが、ランダムアクセスイテレータを作成するのははるかに困難です(正確に正しく理解する必要がある多くのトリッキーな数学)。

2つのポインタの違いは(他の誰かが言ったように)になり::std::ptrdiff_tます。これは、プラットフォームごとに異なるタイプになります。私は64ビットのFedora14でgccを使用していますが、そのタイプはlong私に適しています。この「型変換」にはオーバーヘッドはありません。それは実際には変換でさえありません。コンパイラーは、2つのポインターが単純な古い数値であるかのように減算を実行し、結果はある種の単純な古い数値になります。型の使用は::std::ptrdiff_t、使用される数値の型が、システム内の任意の2つのポインター間の差を保持するのに十分な大きさであることを確認することです。

于 2011-03-09T01:09:27.090 に答える
0

これらit-&v[0]は本当に私を怖がらせます..もしかしてit->v[0]?lower_bound の戻り値の型はです。!valarray<double>::iteratorの代わりにそれを使用してください。double*他のディフェンシングの問題はすべて自動的に解消されます。たとえば、*itandは実行できますが、 はポインターではなく反復子であるため、it++実行できません。その値を取得しようとするすべての試みを違法にする -iteratorit->v[0]である可能性が非常に高いです。v.end()

イテレータの詳細: http://www.cppreference.com/wiki/iterator/start

編集:ああ、なるほど、恐ろしいポインタ演算を使用しています! それはすっごくCです、私たちはもうそれをしません;)

于 2011-03-09T01:14:42.910 に答える