2016-08-29 1 views
5

-Code unten kompiliert und arbeitet sowohl in Visual Studio und g ++:Ungültige Verwendung von unvollständigem Typ, Referenz vs Zeiger

class A; 
A* getRef(void); 
char (&func(...))[2]; 

int main() { 
    bool isDefault = sizeof(func(getRef()))==2; 
    std::cout << isDefault << std::endl; //prints 1 
    return 0; 
} 

Next Code noch kompiliert (und Werke) in Studio, aber g ++ Staaten ist dies invalid use of incomplete type 'class A':

Ist dies ein grundlegend falscher Code, der von einem Compiler abgelehnt werden sollte (und wenn ja, warum VS Compiler keine Warnungen erzeugt)? Oder gibt es tatsächlich einen Unterschied zwischen Zeigern und Referenzen in diesem Zusammenhang, die mir nicht bekannt sind?

+0

@Franck, das OP versucht nicht, 'sizeof (A &)' zu bekommen. 'A &' ist ein Argument für 'func'. –

+0

@RSahu Leider habe ich den 'func' Anruf verpasst. – Franck

+0

@RSahu: Aber der Verweis (auf unvollständigen Typ) wird als tatsächliches Argument für ein Auslassungsargument verwendet. Und das macht es ein bisschen subtil. –

Antwort

4

Der entscheidende Aspekt des geänderten Codes besteht darin, dass ein Verweis auf den unvollständigen Typ als tatsächliches Argument an ein formales Ellipsenargument übergeben wird.

C++ 11 §5.2.2/7, um Argumente zu Auslassungs:

Die L-Wert-zu-R-Wert (4,1), array-zu-Zeiger (4,2) und Standard-Konvertierungen von Funktion zu Zeiger (4.3) werden für den Argumentausdruck durchgeführt. Ein Argument mit (möglicherweise cv-qualifiziertem) Typ std::nullptr_t wird in Typ void* (4.10) konvertiert. Wenn nach diesen Konvertierungen das Argument keine Arithmetik, Aufzählung, Zeiger, Zeiger auf Member oder Klassentyp aufweist, ist das Programm schlecht formatiert.

Dann für die L-Wert-to-rvalue Umwandlung finden wir

C++ 11 §4.1/1:

A glvalue (3,10) eine nicht-Funktion, nicht-Array-Typ T kann auf eine prvalue umgewandelt werden. Wenn T ein unvollständiger Typ ist, ist ein Programm, das diese Konvertierung erfordert, schlecht gebildet.

Als ich es gelesen, aber das ist nur mein Bauchgefühl Interpretation, ist ein Verweis auf T ein glvalue vom Typ T, die hier nicht vollständig ist, schlecht gebildet Code ergibt.

2

Egal was die Argumente func sind sizeof(func(getRef())) wird gleich 2 sein. Die Argumente zu func müssen nicht ausgewertet werden, um auf diese Antwort zu kommen.

Aus dem C++ 11 Standard:

5.3.3 Sizeof

1 Die sizeof Operator ergibt sich die Anzahl von Bytes in der Objektdarstellung seines Operanden. Der Operand ist entweder ein Ausdruck, der ein nicht bewerteter Operand ist (Abschnitt 5), oder ein in Klammern gesetzter Typ-ID.

In Ihrem Fall ist der Operand ein Ausdruck, der ein unbewerteter Operand ist. Der Compiler braucht func(getRef()) nicht auszuwerten, um den Wert sizeof(func(getRef())) zu erhalten.

Daher schließe ich, dass g++ ist übergreifend in was es braucht.


Es scheint, dass g ++ 's Umgang mit variablen Argumentfunktionen der Schuldige ist. Es funktioniert gut, wenn func modifiziert

char (&func(A&))[2]; 

Siehe sein, um es bei http://ideone.com/YQD9v0 arbeiten.

+0

Nun, diese Art von vereitelt den ursprünglichen Zweck des Codes (um 'char func (A &)' zu deklarieren und somit herauszufinden, ob 'A' ein vollständiger Typ ist). Danke für die Eingabe. – Abstraction

Verwandte Themen