不明白这段代码(它没有条件运行)

时间:2012-05-15 01:36:49

标签: c++

我正在学习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);
        }
    }

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;
    }
}

4 个答案:

答案 0 :(得分:18)

不,您不需要ifwhile语句来引入新级别的范围。基本上,{符号会打开一个新的范围级别,}会结束它。通常的作用域规则适用,例如,在此新块中定义的变量未定义,在块对象的末尾运行析构函数,并且上面作用域级别中与另一个相同的变量将被遮蔽。

常见用例在switch语句中。例如,

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

如果没有case语句中的{ },编译器会抱怨多次定义的标识符。

答案 1 :(得分:7)

这对{}正在创建一个本地scope。在范围的最后,编译器将自动为在该范围内声明的所有堆栈变量(如果存在)调用析构函数。

在您的情况下,groot_set的析构函数将在范围的末尾调用。

我能想到的一个非常常见的用途是在处理线程时获取互斥锁。假设您有一个名为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的析构函数,以确保释放互斥锁。

答案 2 :(得分:4)

如果你指的是代码块有一组额外的大括号,那么在处理堆栈上的短期对象时,这在C ++编程中并不罕见,在这种情况下Graphstd::vector<Cell*>个对象。一对花括号创建一个新的范围。它们不必附加到任何控制语句中。因此,在这种情况下,临时范围用于确保Graphvector对象在超出范围时快速释放。如果没有的额外大括号,在外部for循环的下一次迭代之前,对象将不会被释放。

答案 3 :(得分:2)

您可以创建这样的额外块。它们习惯于增加额外的范围。在您的示例中,G将不会在该块之前或之后存在。