c++ - decltype(auto) foo() 在没有任何警告的情况下返回本地引用

标签 c++ g++ c++14

在使用现代 C++ 中的示例时,我编写了以下代码。

#include <string>
#include <iostream>

static int count = 0;

class Counter
{
public:
    Counter() { ++count; };
    Counter(Counter& r) { ++count; };
    Counter(Counter&& r) { ++count; };
    ~Counter() { --count; };

    void foo() {};
};

decltype(auto) foo_warn()
{
    Counter c;
    return (c);             // Warning about returning local reference
}

decltype(auto) foo_no_warn()
{
    Counter c;
    return 1==1 ? c : c;    // No warning, still local reference returned
}

int main()
{
    Counter& a = foo_warn();
    Counter& b = foo_no_warn();

    std::cout << count << std::endl;  // prints 0

    a.foo();
    b.foo();

    return 0;
}

使用命令编译的代码:

g++-6 -std=c++14 -Wall -O0 decl_fail.cpp -o decl_fail

输出:

g++-6 -std=c++14 -Wall -O0    decl_fail.cpp   -o decl_fail
decl_fail.cpp: In function ‘decltype(auto) foo_warn()’:
decl_fail.cpp:19:10: warning: reference to local variable ‘a’ returned [-Wreturn-local-addr]
  Counter a;
          ^

我很清楚 decltype(auto) 返回表达式的引用(但仍然不直观),因此 ab 是无效引用(由 count==0 证明)。

问题是为什么编译器没有在 foo_no_warn 中警告我?

我是在编译器中发现了错误还是这是某种可以解释的行为?

最佳答案

首先让我们声明问题与 decltype(auto) 没有显式相关,因为如果函数显式返回 Counter&,您将得到几乎相同的结果。

您可以考虑以下代码:

typedef std::vector<int> Type;

class DataContainer {
public:
    DataContainer() : data(Type(1024, 0)) {}
    const Type& getData() const { return data; }

private:
    const Type data;
};

const Type& returnLocalRef()
{
    DataContainer container;
    const Type& data = container.getData();
    return data; // o! returning a ref to local - no warning for most compilers
}

虽然返回了本地引用,但编译器在 VS2015 和 gcc48(使用 -Wall)中都没有发出警告。但是,如果您从 const Type& data 中删除引用,编译器会立即发现问题。您应该将这种行为视为错误吗?有争议。

编译器的基本工作是编译代码。它警告开发人员注意一些明显的问题,但在大多数情况下,它不会对程序逻辑进行任何更深入的分析(编译时间会受到影响)。 这就是开发和应该使用代码静态分析工具的目的。

所描述的情况可以被认为是一个简单的例子,但单层间接就足以“愚弄”编译器。因为要验证这一点,编译器需要检查从 getData 方法实际返回的内容。

做一个简单的修改:

Type globalData;
...
const Type& getData() const { return globalData; }

将使从 returnLocalRef 函数返回的引用有效。 因此,这可以被认为是编译器在分析复杂性和时间效率之间的权衡。

关于c++ - decltype(auto) foo() 在没有任何警告的情况下返回本地引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39490912/

相关文章:

c++ - 是否有 g++ 或 clang++ 调试选项来指导可变参数模板

c++ - 变量模板编译时数组

c++ - 如何正确配置 Clang?

c++ - 为什么 g++ 不使用 -I 选项?

c++ - 从(指向 const 的指针)到(指向非常量的指针)的强制转换是否无效 C++?

c++ - MinGW 中预处理器 g++ 的奇怪行为

c++11可变参数编程,如何定义 vector 塔

c++ - 如果一个类继承 NSObject 会有多少开销

c++ - 在 VC++ PPL 中,如何创建同步返回的任务返回方法?

c++ - Qt (C++) : multiple definitions of functions