2012-05-15 2 views
8

私はC++を学んでおり、私が読んだ本の中でこれを実際に見たことはありません。私はコードを読んでコメントしたかったので、よく学び、走っているが条件がない奇妙なコード部分を見つけました。私が読んだこと(そして他の言語での私の経験から、ブロックのためのif、while、forまたはsomethingが必要です)。このコードブロックは理解できません(条件なしで実行します)

tbbスレッドパッケージを見ていますので、スレッドやC++の起動に関連しているかどうかはわかりません(もしこれをC++の共通のものと認識していれば、おそらくtdd固有です)。

実際に内部のコードが何を理解していると思いますが、どのようにトリガされたか、実行されたかわかりません。何か案は?ここで

はセクションです:

{ 
     //this is the graph part of the code 
     Graph g; 
     g.create_random_dag(nodes); 
     std::vector<Cell*> root_set; 
     g.get_root_set(root_set); 
     root_set_size = root_set.size(); 
     for(unsigned int trial=0; trial<traversals; ++trial) { 
      ParallelPreorderTraversal(root_set); 
     } 
    } 

P.S.ここではファイル全体が役に立ちます(上記のコードはmain()の真ん中にあります)。

#include <cstdlib> 
#include "tbb/task_scheduler_init.h" 
#include "tbb/tick_count.h" 
#include "../../common/utility/utility.h" 
#include <iostream> 
#include <vector> 
#include "Graph.h" 

// some forward declarations 
class Cell; 
void ParallelPreorderTraversal(const std::vector<Cell*>& root_set); 

//------------------------------------------------------------------------ 
// Test driver 
//------------------------------------------------------------------------ 
utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads); 
static unsigned nodes = 1000; 
static unsigned traversals = 500; 
static bool SilentFlag = false; 

//! Parse the command line. 
static void ParseCommandLine(int argc, const char* argv[]) { 
    utility::parse_cli_arguments(
      argc,argv, 
      utility::cli_argument_pack() 
       //"-h" option for for displaying help is present implicitly 
       .positional_arg(threads,"n-of-threads","number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.") 
       .positional_arg(nodes,"n-of-nodes","number of nodes in the graph.") 
       .positional_arg(traversals,"n-of-traversals","number of times to evaluate the graph. Reduce it (e.g. to 100) to shorten example run time\n") 
       .arg(SilentFlag,"silent","no output except elapsed time ") 
    ); 
} 

int main(int argc, const char* argv[]) { 
    try { 
     tbb::tick_count main_start = tbb::tick_count::now(); //tbb counter start 
     ParseCommandLine(argc,argv); 

     // Start scheduler with given number of threads. 
     std::cout << threads << std::endl; 
     for(int p=threads.first; p<=threads.last; ++p) { 
      tbb::tick_count t0 = tbb::tick_count::now(); //timer 
      tbb::task_scheduler_init init(4); //creates P number of threads 
      srand(2); //generates a random number between 0-2? 
      size_t root_set_size = 0; 
      { 
       //this is the graph part of the code 
       Graph g; 
       g.create_random_dag(nodes); 
       std::vector<Cell*> root_set; 
       g.get_root_set(root_set); 
       root_set_size = root_set.size(); 
       for(unsigned int trial=0; trial<traversals; ++trial) { 
        ParallelPreorderTraversal(root_set); 
       } 
      } 
      tbb::tick_count::interval_t interval = tbb::tick_count::now()-t0; //counter done 
      if (!SilentFlag){ //output the results 
       std::cout 
        <<interval.seconds()<<" seconds using "<<p<<" threads ("<<root_set_size<<" nodes in root_set)\n"; 
      } 
     } 
     utility::report_elapsed_time((tbb::tick_count::now()-main_start).seconds()); 

     return 0; 
    }catch(std::exception& e){ 
     std::cerr 
      << "unexpected error occurred. \n" 
      << "error description: "<<e.what()<<std::endl; 
     return -1; 
    } 
} 
+0

http://en.wikibooks.org/wiki/C%2B%2B_Programming/Scope/Examples - 具体的には「//複雑なスコーププログラム」のセクション – WernerCD

答えて

18

ありませんあなたはスコープの新しいレベルを導入するifまたはwhile文は必要ありません。基本的に{シンボルは新しいスコープレベルを開き、}はそれを終了します。通常、この新しいブロック内で定義された変数は、ブロックオブジェクトの末尾では定義されていません。デストラクタが実行され、上のスコープレベルの別の変数と同じ名前の変数がシャドーされます。

一般的な使用例はswitchです。例えば、コンパイラは、多重定義された識別子に文句を言うだろうcase文で{}なし

switch (a) 
{ 
    case 1: 
    { 
     int i; 
    } 
    case 2: 
    { 
     int i; //note reuse of variable with the same name as in case 1 
    } 
} 

+0

興味深い.thanks私は実際の生活が何であるか疑問に思いますか?クリーンアップ(無料など)を簡単にすることや目的は何か? – Lostsoul

+3

はい、ローカル変数のスコープをより細かく制御するために使用されます。ローカル変数のどこからアクセスできるだけでなく、スタックベースのオブジェクトであれば解放されます。 –

+2

同じ変数名を必要に応じて再利用することもできますが、外側と内側の同じ名前は2つの並行スコープほど有用ではありません。 – chris

2

このような余分なブロックを作成することができます。彼らは範囲の追加レベルを課すために使用されます。あなたの例では、Gはそのブロックの前後に存在しません。

7

{とのペアはローカルscopeを作成しています。スコープの終わりに、コンパイラは、そのスコープ内で宣言されたすべてのスタック変数(存在する場合)のデストラクタを自動的に呼び出します。

あなたのケースでは、groot_setのデストラクタがスコープの最後に呼び出されます。

私が考えることのできるのは、スレッドで作業するときにミューテックスロックを取得することです。たとえば、mutexオブジェクトを受け入れてロックを取得するクラスLockがあるとします。上記を行うことの利点は、{ ... }ブロック内のコードはまだ、コンパイラを例外をスローした場合でもということです

{ 
    Lock lock(mutex); // the Lock constructor will acquire a lock on mutex 

    // do stuff 
} // Here the Lock destructor runs and releases the lock on mutex, allowing 
    // other threads to acquire a lock 

:その後、あなたは次のように同時アクセスから保護する必要のあるコードのクリティカルセクションを囲むことができますLockのデストラクタを呼び出して、mutexロックが解放されることを保証します。

4

コードブロックに余分な中カッコがあるということは、スタック上の短命オブジェクト(この場合はGraphstd::vector<Cell*>オブジェクト)を扱う際にはC++プログラミングでは珍しくありません。中括弧のペアが新しいスコープを作成します。それらは、いかなる制御ステートメントにも添付する必要はありません。この場合、一時的なスコープを使用して、範囲外になったときにGraphオブジェクトとvectorオブジェクトが迅速に解放されるようにします。余分な中カッコが存在しない場合、オブジェクトはループの次の反復まで解放されません。forループ。

関連する問題