gpt4 book ai didi

c++ - GCC 对可能有效的代码抛出 init-list-lifetime 警告?

转载 作者:行者123 更新时间:2023-12-01 14:07:36 24 4
gpt4 key购买 nike

我在 Debian 不稳定的 GCC 9.3.0 上运行。
我从事的一个项目最近发生了一个变化,该项目引入了类似于下面的代码。

#include <initializer_list>
#include <map>
#include <vector>

std::map<int, std::vector<int>> ex = []{
/* for reused lists */
std::initializer_list<int> module_options;

return (decltype(ex)) {
{1, module_options = {
1, 2, 3
}},
{2, module_options},
};
}();
这个想法是初始化列表的相同子部分首先在顶部声明,定义并分配给 std:initializer_list。第一次使用时变量,然后在多个地方使用。这很方便,有些人可能会认为更具可读性,这就是它被接受的原因。
一切都很好,直到几天前 GCC 开始抛出 init-list-lifetime代码上的警告。我们使用 -Werror在我们的回归中,所以这对我来说失败了。我还尝试使用 clang 9.0.1 进行编译,它不会引发警告。
<source>: In lambda function:
<source>:12:9: warning: assignment from temporary 'initializer_list' does not extend the lifetime of the underlying array [-Winit-list-lifetime]
12 | }},
| ^
根据 cppreference :

The underlying array is not guaranteed to exist after the lifetime of the original initializer list object has ended. The storage for std::initializer_list is unspecified (i.e. it could be automatic, temporary, or static read-only memory, depending on the situation).


所以我的理解是,在包含初始化程序列表的范围内定义的通用初始化程序列表值具有以封闭初始化程序列表结束的生命周期。从前面的 cppreference 页面中,它提到 std::initializer_list是一个“轻量级代理对象”,这意味着它不获取临时对象的所有权或延长它的生命周期。这意味着底层数组不能保证在以后的使用中存在,这就是引发警告的原因。这个分析正确吗?
我可以通过移动 std::initializer_list 来防止出现警告。变量初始化声明。有关项目中问题的完整详细信息,请参阅 PR .

最佳答案

So my understanding is that the common initializer list value, being defined within the scope of an encompassing initializer list, has a lifetime that ends with the enclosing initializer list


您说的是由prvalue 表达式 {1, 2, 3} 创建的对象。 , 对?
decl.init.list/6 中有一个例子,

The array has the same lifetime as any other temporary object ([class.temporary]), except that initializing an initializer_­list object from the array extends the lifetime of the array exactly like binding a reference to a temporary. [Example:

// ...
std::initializer_list<int> i3 = { 1, 2, 3 };
// ...
其中标准(或草案)说

For i3, the initializer_­list object is a variable, so the array persists for the lifetime of the variable.


这表明该对象必须被物化并且应该延长其生命周期。
但是,您没有初始化 initializer_list表达式中的对象,因为您的变量已经初始化。如果我们将您的代码重写为对名义上的调用
module_options.operator=({1, 2, 3})
那么我们不会期望临时生命周期延长到函数调用结束之后。
我曾怀疑这个临时变量仍然会持续到完整表达式的末尾,因为我认为绑定(bind)一个引用应该是 延长 它的生命周期而不是减少它:但不可否认 class.temporary/6说“……在引用的生命周期内持续存在……”而不是“……在 至少 生命周期内持续存在……”
但是,这确实意味着原始代码的以下变体应该可以满足您的需求:
std::map<int, std::vector<int>> ex = []{
/* for reused lists */
std::initializer_list<int> module_options { 1, 2, 3 };

return (decltype(ex)) {
{1, module_options},
{2, module_options},
};
}();

关于c++ - GCC 对可能有效的代码抛出 init-list-lifetime 警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62877374/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com