Podczas odtwarzania przykładami z Modern C++ napisałem poniższy kod.decltype (auto) foo() zwraca lokalny odnośnik bez żadnego ostrzeżenia
#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;
}
kod skompilowany z poleceniem:
g++-6 -std=c++14 -Wall -O0 decl_fail.cpp -o decl_fail
wyjściowa:
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;
^
Jest dla mnie jasne, że decltype(auto)
zwraca odniesienie do wyrażenia (ale jeszcze nie intuicyjny), dlatego a
i b
są nieprawidłowymi odniesieniami (sprawdzonymi przez count==0
).
Pytanie brzmi, dlaczego kompilator nie ostrzegł mnie o tym w foo_no_warn
?
Czy właśnie znalazłem błąd w kompilatorze, czy to jest jakieś wytłumaczalne zachowanie?
Wydaje się być błędem. clang i gcc do 5 włącznie zgłaszają to ostrzeżenie. – Hayt
@ Powrót AlgirdasPreidžius (c) rzeczywiście zwraca referencję. –
możesz sprawdzić kilka wersji kompilatora dla tego tutaj: http://gcc.godbolt.org/ – Hayt