STD :: initializer_list的寿命递归使用
我正在尝试使用std :: prinitizer_list
来定义和输出递归数据结构。在下面的示例中,我正在处理一个列表,其中每个元素可以是整数或同一类型列表的另一个实例。我使用中间变体类型来做到这一点,该类型可以是初始化列表或整数。
我不清楚的是std :: prinistizer_list
的寿命是否足够长以支持此用例,还是我会遇到不一致的内存访问的可能性。该代码运行良好,但我担心这不能保证。我的希望是std :: prinitizer_list
和任何中间的临时std :: prinitizer_list
用于创建顶级列表的对象仅在顶级之后清理表达是完整的。
struct wrapped {
bool has_list;
int n = 0;
std::initializer_list<wrapped> lst;
wrapped(int n_) : has_list(false), n(n_) {}
wrapped(std::initializer_list<wrapped> lst_) : has_list(true), lst(lst_) {}
void output() const {
if (!has_list) {
std::cout << n << ' ';
} else {
std::cout << "[ ";
for (auto&& x : lst) x.output();
std::cout << "] ";
}
}
};
void call_it(wrapped w) {
w.output();
std::cout << std::endl;
}
void call_it() {
call_it({1}); // [ 1 ]
call_it({1,2, {3,4}, 5}); // [ 1 2 [ 3 4 ] 5 ]
call_it({1,{{{{2}}}}}); // [ 1 [ [ [ [ 2 ] ] ] ] ]
}
这是安全的还是不确定的行为?
I am trying to use std::initializer_list
in order to define and output recursive data-structures. In the example below I am dealing with a list where each element can either be an integer or another instance of this same type of list. I do this with an intermediate variant type which can either be an initializer list or an integer.
What is unclear to me is whether the lifetime of the std::initializer_list
will be long enough to support this use-case or if I will be experiencing the possibility of inconsistent memory access. The code runs fine, but I worry that this is not guaranteed. My hope is that the std::initializer_list
and any intermediate, temporary std::initializer_list
objects used to create the top-most list are only cleaned up after the top-level expression is complete.
struct wrapped {
bool has_list;
int n = 0;
std::initializer_list<wrapped> lst;
wrapped(int n_) : has_list(false), n(n_) {}
wrapped(std::initializer_list<wrapped> lst_) : has_list(true), lst(lst_) {}
void output() const {
if (!has_list) {
std::cout << n << ' ';
} else {
std::cout << "[ ";
for (auto&& x : lst) x.output();
std::cout << "] ";
}
}
};
void call_it(wrapped w) {
w.output();
std::cout << std::endl;
}
void call_it() {
call_it({1}); // [ 1 ]
call_it({1,2, {3,4}, 5}); // [ 1 2 [ 3 4 ] 5 ]
call_it({1,{{{{2}}}}}); // [ 1 [ [ [ [ 2 ] ] ] ] ]
}
Is this safe, or undefined behavior?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您所做的应该是安全的。 ISO标准第6段的第6.7.7节描述了第三个也是最后一个上下文,其中临时性在与完整表达式的末端不同的点被摧毁。脚注(35)明确表示,这适用于
Intializer_list
及其基本临时数组的初始化:...(
glvalue
是每7.2.1,一个评估确定对象的身份,位景或功能的表达式),然后列举条件。在(6.9)中,它特别提到:当我阅读它时,这保护了为
call_it
构建最终参数所需的一切,这是您的意图。What you're doing should be safe. Section 6.7.7 of the ISO Standard, paragraph 6, describes the third and last context in which temporaries are destroyed at a different point than the end of the full expression. Footnote (35) explicitly says that this applies to the initialization of an
intializer_list
with its underlying temporary array:...(where a
glvalue
is, per 7.2.1, an expression whose evaluation determines the identity of an object, bit-field, or function) and then enumerates the conditions. In (6.9), it specifically mentions that:As I read it, this protects everything needed to build up the final argument to the top call to
call_it
, which is what you intend.据我所知,该程序的行为不确定。
成员声明
std :: prinitizer_list&lt; trapp&gt; lst;
需要完成类型,因此将隐式实例化std :: prinitizer_list&lt; trapped&gt;
。此时,
包装
是一种不完整的类型。根据 [res.on.functions] /2.5 ,如果没有说明特定的例外,请实例化具有不完整类型的标准库模板,因为模板参数是未定义的。我在
另请参见活动 lwg问题2493 。
As far as I can tell the program has undefined behavior.
The member declaration
std::initializer_list<wrapped> lst;
requires the type to be complete and hence will implicitly instantiatestd::initializer_list<wrapped>
.At this point
wrapped
is an incomplete type. According to [res.on.functions]/2.5, if no specific exception is stated, instantiating a standard library template with an incomplete type as template argument is undefined.I don't see any such exception in [support.initlist].
See also active LWG issue 2493.