野牛价值移动/效率
Bison value moving / efficiency
我正在根据野牛的语义值构建我的解析数据结构。一个特定的结构是 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;])[
}
不幸的是,我几乎无法破译它来确定移动数据结构(如 std::vector)的效率,部分原因是我对 m4 语法一无所知。
鉴于我的语法:
%define api.token.constructor
%define api.value.type variant
%type < std::vector<double> > numlist
...
numlist:
num { $$ = std::vector<double>(); $$.push_back(); }
| numlist "," num { $$ = ; $$.push_back(); }
;
我不确定性能影响。请注意,这将使用 C++98 编译器而不是 C++11 编译器进行编译;因此不会有移动语义。
我猜 $$ = std::vector<double>()
语句可以删除;我假设它已经是默认构造的,但我没有测试过,我不确定 bison 的内部变体类型是如何工作的。我特别感兴趣的是 $$ = ; $$.push_back();
是否会为要添加的每个项目复制矢量?
我无法确定这是否是将类型切换为 std::vector<double> *
的情况;不可否认,使用 bison 的变体类型背后的大部分原因是使用普通的 C++ 类型而不是指针联合。
我对一个解析器也有类似的好奇心,它实际上使用了 C++11/14,特别是 std::unique_ptr
。如果分配了左递归规则的一行,比如 $$ = std::make_unique<...>(...)
,下面的代码可以做到 $$ = ; $$->...
吗?
我不是 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;
位于 parser::parse
方法内部,其中 yylhs
是类型 stack_symbol_type
的局部变量, yystack_
是 parser
class 类型 stack_type
(包含 stack_symbol_type
)。
看起来答案是是,当你$$ =
时,整个向量将被复制,我不知道编译器如何优化它. as
的声明如下:
template <typename T>
T& as();
使用 const
变体,所以影响是在类型 T
上完成的,在您的情况下是 std::vector<double>
,因此制作了一个副本。即使您使用 c++11 移动语义,也会进行复制,因为 RHS 不是 xvalue
.
我正在根据野牛的语义值构建我的解析数据结构。一个特定的结构是 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;])[
}
不幸的是,我几乎无法破译它来确定移动数据结构(如 std::vector)的效率,部分原因是我对 m4 语法一无所知。
鉴于我的语法:
%define api.token.constructor
%define api.value.type variant
%type < std::vector<double> > numlist
...
numlist:
num { $$ = std::vector<double>(); $$.push_back(); }
| numlist "," num { $$ = ; $$.push_back(); }
;
我不确定性能影响。请注意,这将使用 C++98 编译器而不是 C++11 编译器进行编译;因此不会有移动语义。
我猜 $$ = std::vector<double>()
语句可以删除;我假设它已经是默认构造的,但我没有测试过,我不确定 bison 的内部变体类型是如何工作的。我特别感兴趣的是 $$ = ; $$.push_back();
是否会为要添加的每个项目复制矢量?
我无法确定这是否是将类型切换为 std::vector<double> *
的情况;不可否认,使用 bison 的变体类型背后的大部分原因是使用普通的 C++ 类型而不是指针联合。
我对一个解析器也有类似的好奇心,它实际上使用了 C++11/14,特别是 std::unique_ptr
。如果分配了左递归规则的一行,比如 $$ = std::make_unique<...>(...)
,下面的代码可以做到 $$ = ; $$->...
吗?
我不是 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;
位于 parser::parse
方法内部,其中 yylhs
是类型 stack_symbol_type
的局部变量, yystack_
是 parser
class 类型 stack_type
(包含 stack_symbol_type
)。
看起来答案是是,当你$$ =
时,整个向量将被复制,我不知道编译器如何优化它. as
的声明如下:
template <typename T>
T& as();
使用 const
变体,所以影响是在类型 T
上完成的,在您的情况下是 std::vector<double>
,因此制作了一个副本。即使您使用 c++11 移动语义,也会进行复制,因为 RHS 不是 xvalue
.