【问题标题】:Why does g++ warn about returning a reference to a temporary为什么g ++会警告返回对临时的引用
【发布时间】:2017-10-06 13:56:55
【问题描述】:

我有以下代码:

constexpr const_reference_t at(size_t p_pos) const
{
    using namespace std;

    return (p_pos > m_size)
        ? throw out_of_range{ string{ "string_view_t::at: pos > size() with pos = " } + to_string(p_pos) }
        : m_begin_ptr[p_pos];
}

编译时,g++ 告诉我:

/home/martin/Projekte/pluto/pluto-lib/stringview.hpp:50:警告:返回对临时 [-Wreturn-local-addr] 的引用 : m_begin_ptr[p_pos]; ^ m_begin_ptr 是:

const_pointer_t m_begin_ptr = nullptr;

而 const_pointer_t 的类型为 const char*

这段代码真的不正确还是错误的警告?如果 g++ 是正确的,那为什么这是暂时的呢?最后,我该如何避免这个警告。

g++ 版本为 7.2.0

我进一步最小化了代码:

static const char* greeting = "hallo, world!";

const char& nth(unsigned n)
{
    return true ? throw "" : greeting[n];
}

int main()
{
    return 0;
}

【问题讨论】:

  • 这是对您所拥有的三元运算符的严重滥用。使用常规的 if 条件来保持理智。
  • 返回一个临时的引用(或指针)意味着调用者接收到一个不再存在的对象的引用。如果调用者用户引用该引用,则行为未定义。在三元表达式中使用 throw 表达式会给出与另一个表达式相同类型的默认初始化结果 - 这将是未初始化的
  • 你能提供一个minimal reproducible example吗?
  • 什么是const_reference_t?
  • 请记住,三元运算符必须将其第二个和第三个参数的类型调整为某种常见类型。 throw "" 的类型是什么? greeting[n] 的类型是什么?他们常见的类型是什么?这与函数声明的返回类型有何关系?为什么代码首先使用三元运算符?使用if ... else 会简单得多,因为您不必为其中一些问题感到困惑。

标签: c++ g++ warnings


【解决方案1】:

当(p_pos > m_size) 条件为true 时,您返回由throw 创建的对象,根据文档创建临时对象。

异常对象是由 throw 表达式构造的未指定存储中的临时对象。

因为函数返回类型是const char&,即引用,编译器试图将临时对象转换为引用,所以你得到了警告。

你不应该尝试返回throw的结果,你只是throw。

我会亲自将三元运算符部分更改为:

if (p_pos > m_size) {
    // throw
}
return m_begin_ptr[p_pos];

【讨论】:

  • 听起来很合理。但在我接受这个答案之前的最后一个问题。为什么编译器会说:警告:返回对临时 [-Wreturn-local-addr] 的引用:m_begin_ptr[p_pos]。这是第二个分支。
  • 我不确定这个,也许是其他人?我个人经常收到 GCC 警告,它没有说明导致原始问题的原因,而是 GCC 抱怨一些问题,这要感谢原始问题的后果。所以你应该知道,来自 GCC 的问题描述并不总是 100% 准确。
猜你喜欢
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
  • 2011-09-24
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
相关资源
最近更新 更多