7

私はc++を学んでいますが、これまで読んだどの本でもこれを見たことがありません。私はコードを読んでコメントしたかったので、よりよく学ぶことができ、実行されているが条件がないコードの奇妙なセクションに出くわしました。私が読んだものから(そして他の言語での私の経験から、あなたはブロックのためにif、while、forまたは何かが必要です)。

私は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);
        }
    }

psそれが助けになるなら、ここにファイル全体があります(上記のコードは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;
    }
}
4

4 に答える 4

18

いいえ、新しいレベルのスコープを導入するためにiforステートメントは必要ありません。while基本的に、{シンボルは新しいスコープ レベルを開き、それを}終了します。通常のスコープ ルールが適用されます。たとえば、この新しいブロック内で定義された変数はブロックの外側では定義されず、ブロック オブジェクト デストラクタの最後で実行され、上のスコープ レベルで別の変数と同じ名前が付けられた変数はシャドウされます。

一般的な使用例はswitchステートメントです。例えば、

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

in the case ステートメントがないと{ }、コンパイラは重複して定義された識別子について文句を言います。

于 2012-05-15T01:40:17.777 に答える
7

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

gあなたの場合、とのデストラクタroot_setはスコープの最後に呼び出されます。

私が考えることができる非常に一般的な用途の 1 つは、スレッドを操作するときにミューテックス ロックを取得することです。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のデストラクタを呼び出して、ミューテックス ロックが確実に解放されることです。

于 2012-05-15T01:44:06.207 に答える
4

コード ブロックに余分な中かっこのセットがあるという事実に言及している場合、これは C++ プログラミングでは、スタック上で有効期間が短いオブジェクト (この場合はGraphandstd::vector<Cell*>オブジェクト) を処理する場合に珍しくありません。中括弧のペアは、新しいスコープを作成します。制御ステートメントに付加する必要はありません。したがって、この場合、Graphおよびvectorオブジェクトがスコープ外に出たときにすぐに解放されるようにするために、一時スコープが使用されています。for追加の中かっこが存在しない場合、オブジェクトは外側のループの次の反復まで解放されません。

于 2012-05-15T01:44:45.127 に答える
2

そのような追加のブロックを作成できます。それらは、追加レベルのスコープを課すために使用されます。あなたの例では、そのブロックの前後に G は存在しません。

于 2012-05-15T01:40:33.713 に答える