野牛价值移动/效率

Zac*_*Zac 5 c++ vector bison move-semantics c++14

我正在从bison的语义值构建我的解析数据结构.一种特殊结构是类型的std::vector<double>.我很好奇野牛内部如何处理移动的语义值.我试着分析c ++.m4文件,发现:

template <typename Base>
  inline
  void
  ]b4_parser_class_name[::basic_symbol<Base>::move (basic_symbol& s)
  {
    super_type::move(s);
    ]b4_variant_if([b4_symbol_variant([this->type_get ()], [value], [move],
                                      [s.value])],
                   [value = s.value;])[]b4_locations_if([
    location = s.location;])[
  }
Run Code Online (Sandbox Code Playgroud)

不幸的是,我无法破译这一点,足以说明移动像std :: vector这样的数据结构的效率,部分原因是我对m4语法的无知.

鉴于我的语法:

%define api.token.constructor
%define api.value.type variant
%type < std::vector<double> > numlist
...
numlist:
    num             { $$ = std::vector<double>(); $$.push_back($1); }
|   numlist "," num { $$ = $1; $$.push_back($3); }
;
Run Code Online (Sandbox Code Playgroud)

我不确定性能影响.请注意,这将使用C++ 98编译器而不是C++ 11编译器进行编译; 因此没有移动语义.

我猜这个$$ = std::vector<double>()陈述可以删除; 我认为它已经默认构建,但我没有测试过,我不确定野牛的内部变体类型是如何工作的.我特别感兴趣的是是否$$ = $1; $$.push_back($3);会为每个要添加的项目复制向量?

我无法确定这是否是将类型切换为的情况std::vector<double> *; 不可否认,使用bison的变体类型背后的大部分原因是使用普通的C++类型而不是指针的联合.


我对解析器也有类似的好奇心,事实上它实际上使用了C++ 11/14 std::unique_ptr.如果分配了左递归规则的一行$$ = std::make_unique<...>(...),那么以下是否能够做到$$ = $1; $$->...

Hol*_*olt 3

我不是 Bison / Yacc 专家,但你可以看看生成的代码:

      {
  case 2:
#line 20 "test.yy" // lalr1.cc:846
    { yylhs.value.as<  std::vector<double>  > () = std::vector<double>();
      yylhs.value.as<  std::vector<double>  > ().push_back(yystack_[0].value.as< double > ()); }
#line 1306 "test.tab.cc" // lalr1.cc:846
    break;

  case 3:
#line 21 "test.yy" // lalr1.cc:846
    { yylhs.value.as<  std::vector<double>  > () = yystack_[2].value.as<  std::vector<double>  > (); 
      yylhs.value.as<  std::vector<double>  > ().push_back(yystack_[0].value.as< double > ()); }
#line 1312 "test.tab.cc" // lalr1.cc:846
    break;
Run Code Online (Sandbox Code Playgroud)

其中位于parser::parse方法内部,其中yylhs是类型的局部变量stack_symbol_type,并且是类型的类的yystack_属性(其中包含)。parserstack_typestack_symbol_type

看起来答案是肯定的,当你这样做时,整个向量将被复制$$ = $1,而且我不知道编译器如何优化它。声明as如下:

template <typename T>
T& as();
Run Code Online (Sandbox Code Playgroud)

使用const变体,因此对类型进行了影响T,在您的情况下是std::vector<double>,因此制作了副本。即使您使用移动语义,也会创建副本,因为 RHS 不是xvalue.