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函数返回的引用有效.因此,这可以被认为是分析复杂性和时间效率之间的编译器的折衷. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |