这种情况有一个错误:
const int& foo() {
const int x = 0;
return x;
}
乃至
const int& foo() {
const std::pair<int,int> x = {0,0};
return x.first;
}
但不是这个:
const int& foo() {
const std::array<int,1> x = {0};
return x[0];
}
并且(不那么令人惊讶)不是这个:
const int& foo() {
const std::vector<int> x = {0};
return x[0];
}
特别是在这种std::vector
情况下,我知道这个警告会非常棘手,因为对于编译器来说,const int&
返回的std::vector<int>::operator[](size_t) const
不是对临时的引用。不过,我实际上对std::array
没有失败感到有点惊讶,因为这种类似的情况确实给了我一个错误:
struct X {
int x[0];
};
const int& foo() {
X x;
return x.x[0];
}
是否有任何流行的编译器有可以捕获这些情况的警告/错误?我可以想象一个保守的版本,它会警告返回来自临时成员函数调用的引用。
我用类似下面的方法绊倒了这个问题,在其中我内联了一系列链接的调用,但是因为 C++ 允许您将 locals 分配给const&
,所以详细版本可以工作,而表面上相同的版本会立即删除临时,留下一个悬空引用:
#include <iostream>
struct A {
int x = 1234;
A() { std::cout << "A::A " << this << std::endl; }
~A() { x = -1; std::cout << "A::~A " << this << std::endl; }
const int& get() const { return x; }
};
struct C {
C() { std::cout << "C::C " << this << std::endl; }
~C() { std::cout << "C::~C " << this << std::endl; }
A a() { return A(); }
};
int foo() {
C c;
const auto& a = c.a();
const auto& x = a.get();
std::cout << "c.a(); a.get() returning at " << &x << std::endl;
return x;
}
int bar() {
C c;
const int& x = c.a().get();
std::cout << "c.a().get() returning at " << &x << std::endl;
return x;
}
int main() {
std::cout << foo() << std::endl;
std::cout << bar() << std::endl;
}
那输出
C::C 0x7ffeeef2cb68 A::A 0x7ffeeef2cb58 ca(); a.get() 在 0x7ffeeef2cb58 返回 A::~A 0x7ffeeef2cb58 C::~C 0x7ffeeef2cb68 1234 C::C 0x7ffeeef2cb68 A::A 0x7ffeeef2cb58 A::~A 0x7ffeeef2cb58 ca().get() 在 0x7ffeeef2cb58 返回 C::~C 0x7ffeeef2cb68 -1