2015-11-16 52 views
5

Clang编译器生成警告编译此代码段,我找不出原因。指针解引用返回引用本地临时对象

const int* Get() { 
    static const int ARRAY[4] = {1, 2, 3, 4}; 
    return &ARRAY[0]; 
} 

const int& Test() { 
    const auto& p = Get(); 
    return (*p); 
} 

warning: returning reference to local temporary object [-Wreturn-stack-address] 
    return (*p); 

GCC在此代码上未显示警告。 我可以解决这样的片段:const auto p = Get(); 但我想知道是否有一些临时的对象,问题在于更深

+0

@ 101010“临时对象”?也许你可以更清楚一点?我们绝对可以引用堆栈中的非const变量。 –

+4

鉴于'p'是一个临时的,'* p'是有效的。我认为这是Clang的误判。 – Jarod42

+1

@JonathanMee:[了解临时工](http://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/) –

回答

4

这一警告是假阳性,因为p指向者不是一个暂时的,尽管p指到一个。有更多的情况是虚假地产生这种警告的;见例如Bug 21218,它采用

char * f() { 
    typedef char* t; 
    const t & r = new char[5]; 
    return r; 
} 

据推测,如果返回类型是一个参考,锵查找常量引用在返回的表达式(已绑定到临时工),没有考虑如何使用它们。

1

答:Clang的警告是不正确的。

让我们一步步通过什么这里发生的情况:

  1. static const int ARRAY[4] = {1, 2, 3, 4};构建的int小号
  2. return &ARRAY[0];一个全局数组返回一个指向全局数组的第一个元素
  3. const auto& p = Get()存储参照指针到全局数组的第一个元素
  4. return (*p);创建对全局数组第一个元素的左值的引用

是个棘手的问题。铿锵似乎错误地认为*p是一个本地价值,事实上我们知道它是一个全球性的。

这个证明的关键是the fact that *p returns an lvalue

+0

_“这很容易做到”,因为它在标准中说得很清楚。 –

+0

@LightnessRacesinOrbit我自己没有该标准的副本,而且我似乎无法找到任何确认解除引用操作符返回了左值的任何在线信息。如果你能指出我的来源,我很乐意将其列入,而不是一个例子来证明我的答案。 –

+1

https://en.wikipedia.org/wiki/Dereference_operator第二句 –