c – decltype(auto)foo()返回本地引用而没有任何警告

在玩现代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)返回表达式的引用(但仍然不直观),因此a和b是无效的引用(由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类型&数据编译器马上赶上问题.你应该考虑这样的行为有错误吗?值得商榷.

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

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

一个简单的修改

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

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

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...