【问题标题】:Problems with returning references to local variables...?返回对局部变量的引用的问题...?
【发布时间】:2021-04-11 11:37:13
【问题描述】:

有人抱怨以下函数不起作用,因为它返回“指向局部变量的指针/迭代器”。这个投诉正确吗?我看不到这个问题...

const Range dummy::foo() const
{
    std::vector<Handle> _handles;
    _handles.reserve(_collection.size());

    for (const auto& pair: _collection)
    {
        _handles.push_back(pair.first);
    }

    return _handles;
}

返回类型:

using Range = boost::any_range<Handle, boost::forward_traversal_tag, const Handle>;

感谢您的解释和建议的解决方案!

【问题讨论】:

  • Range 的类型是什么?
  • 永远不允许返回对函数局部变量的引用。一旦函数返回,所有函数 loval 变量都会被销毁,留下对它们的任何引用。
  • 投诉以下功能无效 -- 谁投诉? C++ 有一种叫做值语义的东西,从它的所有外观来看,您返回的是一个值,而不是指针、迭代器或引用。
  • 我的猜测是boost::any_range 只是保存了一个迭代器对,而不是整个向量的副本,当函数返回时,这些迭代器变得无效。
  • const Range dummy::foo() const 更改为std::vector&lt;Handle&gt; dummy::foo() const

标签: c++ vector boost iterator local-variables


【解决方案1】:

这个投诉正确吗?

是的。 _handles 是一个自动变量,您返回一个引用它的范围。范围基本上是对迭代器 + 哨兵对的抽象。返回的范围将在函数之外无效。

我该如何解决这个问题

正确的实现是返回一个转换适配器范围。可能是这样的:

return _collection | boost::adaptors::map_keys;

【讨论】:

  • 如果需要 Range 作为返回类型,我该如何解决这个问题?
  • 次要:oneliner return _collection | boost::adaptors::map_keys; 更直接。还有一些historical context in my answer
  • @sehe 谢谢。我已经编辑了答案。我确实猜到了更具体的适配器可能已经存在于 Boost 中,但在一分钟的搜索中找不到它。
【解决方案2】:

有趣的是,我一个月前在这里的回答中预测到了这一点:How to convert a single object to a boost::any_range?

问题和你的 initializer_list 差不多:

该方法调用未定义行为,因为初始化列表在返回后不存在。

这里同样适用于向量。

您当然可以简单地返回向量本身,而不是迭代器包装范围。否则,您可以使用我在其他答案中使用的完全相同的技术,其中我构建了一个单例范围(使用值语义)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-14
    相关资源
    最近更新 更多