警告 C26449

当临时文件失效时,从该临时文件创建的 gsl::spanstd::string_view 将变为无效 (gsl.view)

C++ Core Guidelines:GSL.view:视图

跨度和视图是可用于引用内存缓冲区的方便且轻量的类型。 但必须谨慎使用它们:虽然它们的界面看起来类似于标准容器,但它们的行为更像指针和引用。 它们不拥有数据,不得从临时缓冲区构造。 此检查重点关注源数据为临时数据而跨度或视图并非临时的情况。 此规则有助于避免在旧代码现代化及跨度或视图采用期间出现的难以察觉却十分危险的错误。 另一个检查所处理的场景略有不同,这些场景涉及跨度引用:C26445 NO_SPAN_REF

请考虑使用 C26815C26816。 这些警告是此警告更为常见的版本。

备注

  • 在为范围或视图调用构造函数且源数据缓冲区属于在同一语句中创建的临时对象时,此规则会发出警告。 此检查包括:

    • 返回语句中的隐式转换;
    • 三元运算符中的隐式转换;
    • static_cast 表达式中的显式转换;
    • 按值返回容器的函数调用。
  • 不会标记为函数调用参数创建的临时对象。 如果目标函数不保留外部变量中的数据指针,则从此类临时对象传递跨度十分安全。

  • 如果范围或视图本身是临时的,则此规则将跳过它们。

  • 检查器中的数据跟踪具有一定限制;因此,可能无法处理涉及多个重新分配或模糊重新分配的复杂方案。

代码分析名称:NO_SPAN_FROM_TEMPORARY

示例

结果类型中的细微差异:

// Returns a predefined collection. Keeps data alive.
gsl::span<const sequence_item> get_seed_sequence() noexcept;

// Returns a generated collection. Doesn't own new data.
std::vector<sequence_item> get_next_sequence(gsl::span<const sequence_item>);

void run_batch()
{
    auto sequence = get_seed_sequence();
    while (send(sequence))
    {
        sequence = get_next_sequence(sequence); // C26449
        // ...
    }
}

若要解决此问题,请确保视图是从至少与视图本身一同存在的对象创建的。 有时,可以通过复制数据来解决问题,有时需要重新设计某些 API 来共享对存在时间足够长的对象的引用,而不是返回临时副本。

另请参阅

C26815
C26816