我正在学习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;
}
}
答案 0 :(得分:18)
不,您不需要if
或while
语句来引入新级别的范围。基本上,{
符号会打开一个新的范围级别,}
会结束它。通常的作用域规则适用,例如,在此新块中定义的变量未定义,在块对象的末尾运行析构函数,并且上面作用域级别中与另一个相同的变量将被遮蔽。
常见用例在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。在范围的最后,编译器将自动为在该范围内声明的所有堆栈变量(如果存在)调用析构函数。
在您的情况下,g
和root_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 ++编程中并不罕见,在这种情况下Graph
和std::vector<Cell*>
个对象。一对花括号创建一个新的范围。它们不必附加到任何控制语句中。因此,在这种情况下,临时范围用于确保Graph
和vector
对象在超出范围时快速释放。如果没有的额外大括号,在外部for
循环的下一次迭代之前,对象将不会被释放。
答案 3 :(得分:2)
您可以创建这样的额外块。它们习惯于增加额外的范围。在您的示例中,G将不会在该块之前或之后存在。