7 Stimmen

Warum darf mein Konstruktor mit nicht-const Referenz als Argument mit temporären Objekten aufgerufen werden?

Ich habe unten einen Beispielcode.

#include

template
class XYZ
{
   private:
   T & ref;
   public:
   XYZ(T & arg):ref(arg)
   {
   }
};
class temp
{
   int x;
   public:
   temp():x(34)
   {
   }
};
template
void fun(T & arg)
{
}
int main()
{
   XYZ<temp> abc(temp());
   fun(temp());  //Dies ist ein Kompilierfehler in gcc, während der obige Code perfekt gültig ist.
}

In dem obigen Code, obwohl der XYZ-Konstruktor das Argument als nicht-const-Referenz annimmt, kompiliert er gut, während die fun-Funktion nicht kompiliert. Ist dies spezifisch für den g++-Compiler oder hat der C++-Standard etwas dazu zu sagen?

Bearbeiten:

g++ -v gibt dies zurück.

gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

12voto

Nawaz Punkte 339767
 XYZ abc(temp());

Es kompiliert, weil es keine Variable-Deklaration ist. Ich bin sicher, dass du denkst, es ist eine Variable-Deklaration, wenn es tatsächlich eine Funktions-Deklaration ist. Der Name der Funktion ist abc; die Funktion gibt ein Objekt vom Typ XYZ zurück und nimmt ein einzelnes (unbenanntes) Argument entgegen, das seinerseits eine Funktion ist, die den Typ temp zurückgibt und kein Argument hat. Siehe diese Themen für eine detaillierte Erklärung:

Und fun(temp()) kompiliert nicht, weil temp() ein temporäres Objekt erstellt und ein temporäres Objekt nicht an einen nicht-const Referenz gebunden werden kann.

Die Lösung ist also folgende: Definiere deine Funktionsvorlage wie folgt:

template
void fun(const T & arg) //beachte das `const`
{
}

5voto

AProgrammer Punkte 49452

Nein, der Standard erlaubt es nicht, ein temporäres Objekt an eine nicht-const-Referenz zu übergeben. (C++0X führte Rvalue-Verweise ein, um dies in einigen kontrollierten Fällen zu ermöglichen), siehe 8.5.3/5 (was für mich zu lang ist, um es zu zitieren, der aussagekräftige Teil ist ansonsten soll die Referenz zu einem nicht-volatilen const-Typ gehören, aber man muss die ganze Liste von Fällen lesen, um zu wissen, dass sie hier nicht zutreffen).

Und

XYZ abc(temp());

ist einfach ein weiteres Beispiel für die verwirrende Syntaxauswertung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X