提问人:w128 提问时间:6/30/2023 最后编辑:JeJow128 更新时间:7/1/2023 访问量:108
为什么循环访问直接通过 std::optional<T>::value() 访问的容器不起作用?
Why doesn't iterate over a container accessed directly through std::optional<T>::value() work?
问:
我正在尝试遍历我通过 .与我的预期相反,如果我首先将其存储到副本中,则行为会有所不同,如果我直接迭代它:std::vector<X>
struct T
std::optional<T>
std::optional<T>
#include <optional>
#include <string>
#include <vector>
// The rest is the same in both implementations
struct Object
{
std::string id;
std::vector<SomeStructType> items;
};
Object readDataFile() { /*....*/ return {}; }
bool dataFileExists() { /*....*/ return true; }
std::optional<Object> getData()
{
if (!dataFileExists()) {
return std::nullopt;
}
Object obj = readDataFile();
return obj;
}
int main()
{
// Implementation 1 - works
auto items = getData().value().items;
for (auto const& item : items)
{
// will normally iterate over items
}
// Implementation 2 - for loop is skipped
for (auto const& item : getData().value().items)
{
// this body will never execute
}
}
我希望这两个人的行为是一样的。为什么实现 2 跳过 for 循环?`
在这两种情况下,读取的文件是相同的,有 .我在提供的代码中省略了一些其他检查和断言,但我不认为它们是相关的。items.size() == 1
nullopt
答:
5赞
JeJo
6/30/2023
#1
希望这两个人的行为是一样的。为什么实现 2 跳过 for 循环?
在第二个实现中,返回一个临时的表达式,它将被销毁表达式的末尾(换句话说,甚至在基于范围的 for 循环开始之前)。getData()
std::optional<Object>
for (auto const &item : getData().value().items)
// ^^^^^^^^^ ---> temporary std::optional<Object>
{
}
因此,基于范围的 for 循环包含无效 .使用此方法会导致程序的未定义行为。在您的情况下,循环未执行。items
话虽如此,如果打开了编译器警告,您早就收到了警告。例如,clang 15 with 说:-Wall -Wextra -pedantic-errors -fsanitize=address,undefined
<source>:25:29: warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
for (auto const& item : getData().value().items)
^~~~~~~~~
1 warning generated.
ASM generation compiler returned: 0
<source>:25:29: warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
for (auto const& item : getData().value().items)
^~~~~~~~~
//...
=================================================================
==1==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7f1262400040 at pc 0x55ba03d4ae30 bp 0x7ffd89ca2a90 sp 0x7ffd89ca2a88
//...
您可以通过一些调整来延长使用寿命。请参阅本文中提到的示例。
评论
1赞
w128
6/30/2023
谢谢。我正在使用 MSVC,它的代码分析没有指出这一点......我猜最好切换到叮当整齐!
评论