【问题标题】:Don't understand this block of code(it runs with no condition)不明白这段代码(它无条件运行)
【发布时间】:2012-05-15 01:36:49
【问题描述】:

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

附言如果有帮助,这里是整个文件(上面的代码在 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;
    }
}

【问题讨论】:

标签: c++


【解决方案1】:

不,您不需要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 语句中没有 { },编译器将抱怨多重定义的标识符。

【讨论】:

  • 有趣..谢谢我想知道现实生活中的用途是什么?使清理(免费等)更容易或目的是什么?
  • 是的,它用于更好地控制局部变量的范围,不仅可以从哪里访问它们,而且如果它们是基于堆栈的对象,还可以在它们何时被释放。
  • 如果您愿意,也可以重用相同的变量名,但在外部和内部使用相同的变量名不如在并行作用域中使用两个。
【解决方案2】:

{} 对正在创建一个本地 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的析构函数确保互斥锁被释放。

【讨论】:

    【解决方案3】:

    如果你指的是代码块有一组额外的大括号,这在 C++ 编程中处理堆栈上的短期对象时并不少见,在本例中为 Graph 和 @987654322 @对象。一对花括号创建了一个新范围。它们不必附加到任何控制语句。因此,在这种情况下,将使用临时范围来确保 Graphvector 对象在超出范围时快速释放。如果额外的大括号不存在,则在外部 for 循环的下一次迭代之前不会释放对象。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2012-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 2014-04-11
        相关资源
        最近更新 更多