【问题标题】:Non-pointer-operand error when dereferencing an iterator into a temporary range将迭代器解引用到临时范围时出现非指针操作数错误
【发布时间】:2018-02-25 18:20:12
【问题描述】:

使用

auto empty_line = [](auto& str){ return str.size() == 0; };

我们可以这样做:

auto line_range_with_first_non_empty = 
                ranges::view::drop_while(ranges::getlines(std::cin),empty_line);
auto input1 = std::stoi(*line_range_with_first_non_empty.begin());

我们也可以这样做:

auto line_range2 = ranges::getlines(std::cin);
auto iter2 = ranges::find_if_not(line_range2,empty_line);
auto input2 = std::stoi(*iter2);

不幸的是,当我尝试将上面的版本缩短为:

auto iter3 = ranges::find_if_not(ranges::getlines(std::cin),empty_line);
// auto input3 = std::stoi(*iter3);

我收到一个错误:

<source>:22:29: error: indirection requires pointer operand ('ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >' invalid)
    auto input3 = std::stoi(*iter3);
                            ^~~~~~

我以为是因为那个无限的范围,但我错了。

auto sin = std::istringstream{"\n\n\nmy line\n"};
auto iter4 = ranges::find_if_not(ranges::getlines(sin),empty_line);
// Error when deref.
// auto input4 = std::stoi(*iter4);

这会产生同样的错误。

<source>:27:29: error: indirection requires pointer operand ('ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >' invalid)
    auto input4 = std::stoi(*iter4);
                        ^~~~~~

ranges::find_if 将范围作为右值时,为什么我不能取消引用?

ranges::getlines 是否返回一个范围?如果是这样,范围应该拥有东西吗?

godbolt.org/g/Yo6tKa

【问题讨论】:

  • 在一个简单的实现中,第三个示例将让find_if_not 将一个迭代器返回到一个临时范围内。该范围将被破坏,使迭代器在可以使用之前悬空,从而导致未定义的行为。范围提案protects against this situation,将其变成编译时错误。
  • @IgorTandetnik 我认为范围从不拥有东西。所以这意味着范围可以拥有东西,对吧?
  • 允许视图的迭代器持有指向其视图的指针,因此它们可以悬空。一些视图保存数据。例如,getlines 视图将在内部 std::string 表示成员中缓存最近读取的行。

标签: c++ c++11 lazy-evaluation range-v3


【解决方案1】:

如果传递给算法的范围是临时的,并且该算法返回一个迭代器,则该迭代器将包装在 dangling 包装器中,以防止您做任何不安全的事情。任务完成。 :-)

【讨论】:

  • 大师本人。 :-) 目前,std::stoi(*ranges::find_if_not(ranges::getlines(sin),empty_line)) 也被阻止,正如我所见,需要使用 get_unsafe()。您是否考虑添加dangling&lt;I&gt;::operator I() const &amp;&amp;?如果是这样,您可能拒绝了这种方法,因为它可以被 std::move.(?)“利用”
  • 我没有考虑过。这让我不舒服。我需要坐下来弄清楚为什么,除了我脑子里的小鬼尖叫着“太微妙了!太可爱了!”
猜你喜欢
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 2013-07-08
  • 1970-01-01
相关资源
最近更新 更多