2012-04-01 8 views
8

Mam do czynienia z ostrzeżeniem GCC, które chcę naprawić. Zasadniczo przechodzę do metody wskaźnik do zmiennej lokalnej, co w moim przypadku jest całkowicie OK. Rozumiem, dlaczego kompilator mówi mi, że jest to potencjalny problem, ale w moim przypadku jest to w porządku.Podjęcie adresu tymczasowego - wymagane obejście

Jak mogę to obejść, na lokalnej przestrzeni? Przekazywanie -fpermissive podczas kompilacji sprawi, że nie uda mi się znaleźć przyszłych problemów. Chcę rozwiązać ten konkretny problem lub obejść go.

Kod jest dostępny tutaj:

#include <cstdio> 

class Integer{ 
public: 
    Integer(int i){ v = i; }; 
    int value(){ return v; }; 
private: 
    int v; 
}; 

int foo(Integer *i); 

int main() 
{ 
    foo(&Integer(12)); 
} 

int foo(Integer *i) 
{ 
    std::printf("Integer = %d\n", i->value()); 
} 

i kompilacja daje mi:

$ g++ test-reference.cpp -O test-reference 
test-reference.cpp: In function ‘int main()’: 
test-reference.cpp:15:18: error: taking address of temporary [-fpermissive] 

$ g++ --version 
g++ (Ubuntu/Linaro 4.6.3-1ubuntu3) 4.6.3 
Copyright (C) 2011 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

EDIT:

Korzystanie const (jak w podejmowaniu foo wziąć const wskaźnik, a oznakowanie value() jako const) daje ten sam błąd.

+0

@jalf zobaczyć odpowiedź Mat, aby zrozumieć. W moim przypadku zmienna jest w zasięgu, gdy wywoływana jest funkcja. – elcuco

+1

Nie możesz zmienić podpisu funkcji na 'int foo (const Integer & i);'? – jrok

Odpowiedz

9
Integer i(12); 
foo(&i); 

To pozbędzie się "problemu adresu tymczasowego", czyli tego, co masz. Nie podajesz adresu zmiennej lokalnej (co powyższe ma, i rzeczywiście jest w porządku w tym przypadku), przechwytujesz adres tymczasowego.

Oczywiście, jeśli foo spróbuje przytrzymać wskazówkę w ten czy inny sposób, problemy pojawią się na linii.

+4

* przechwytujesz adres tymczasowy, który jest bardzo podejrzany. * Nie, to nie jest podejrzane. Zachowanie jest dobrze zdefiniowane, ' 12.2/3' * Obiekty tymczasowe są niszczone jako ostatni krok w ocenie pełnego wyrażenia, które (leksykalnie) zawiera punkt, w którym zostały utworzone *. –

+0

To nie jest bardziej niebezpieczne niż odniesienie do wartości r. – Puppy

+0

Ok, didn ' Oznacza to, że był on nieważny, po prostu (IMO) podejrzany – Mat

3
template<typename T> const T* rvalue_address(const T& in) { 
    return &in; 
} 

Moim zdaniem powinno być tak samo legalne wziąć const T* jako const T&, ale to banalne funkcja grzejniku wykonać konwersję.

+2

A teraz mamy kod, za który MSVC wyda ostrzeżenie. :-) –

4

GCC jest w tym przypadku błędne. Twoja liczba całkowita jest wartością rażącą i przyjęcie adresu wartości rublicznej jest nielegalne.

§5.3.1 Unary operators, Section 3

The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id.

Clang daje błąd w tym przypadku:

error: taking the address of a temporary object of type 'Integer' [-Waddress-of-temporary] 
    foo(&Integer(12)); 
     ^~~~~~~~~~~~ 
+3

GCC nie jest źle, odrzucił go z 'error:' ponieważ jest nielegalny. '-fpermissive' jest rozszerzeniem GCC, które zasadniczo mówi" tak, w porządku, wiem, co miałeś na myśli * ". Rozszerzenia mogą wykonywać wszelkie niestandardowe rzeczy, które im się podobają, ponieważ, no cóż, są niestandardowymi rozszerzeniami. – ams

+0

Standard wymaga diagnostyki dla źle sformułowanego programu, chyba że określono inaczej. Ostrzeżenie jest diagnostyczne. Nawet jeśli GCC wyemitował tylko ostrzeżenie * bez * -pewnego, to nie byłby to problem zgodności. –

Powiązane problemy