Forum: Compiler & IDEs C++ Fehler: invalid initialization of non-const reference


von Klaus (Gast)


Lesenswert?

Folgender Code compiliert nicht:

1
static int*& test()
2
{
3
    static int x[] = {1, 1, 2, 3, 5};
4
    return x; // error!
5
}

Der Compiler meldet hier
1
invalid initialization of non-const reference of type 'int*&' from a temporary of type 'int*'

Dies verstehe ich nicht. Meines Erachtens ist dieser Code in Ordnung, da 
x keine auto Variable vom Stack ist, sondern static ist.

Was ist hier das Problem?

von Peter II (Gast)


Lesenswert?

bei c++ wird x erst beim aufruf von test initialiert. Das geht scheinbar 
nicht bei arrays. Wenn du das als C übersetzt dann sollte es gehen weil 
es es vor main macht.

von Facebook (Gast)


Lesenswert?

Klaus schrieb:
> static int*& test()

Geht wohl eher da drum..

von Klaus W. (mfgkw)


Lesenswert?

Wozu soll das & gut sein?

von Klaus W. (mfgkw)


Lesenswert?

Abgesehen davon (um Mißverständnisse zu vermeiden):
Das static vor der Funktionsdeklaration bezieht sich nicht auf
den Rückgabetyp der Funktion (also nicht static int*... als
Rückgabe), sondern darauf daß die Funktion nur in der aktuellen
Datei sichtbar ist.

von Klaus (Gast)


Lesenswert?

> bei c++ wird x erst beim aufruf von test initialiert. Das geht scheinbar
> nicht bei arrays. Wenn du das als C übersetzt dann sollte es gehen weil
> es es vor main macht.

Folgendes geht dann wieder
1
static int*& test2()
2
{
3
    static int* x;
4
    return x;
5
}

Aber auch folgendes:
1
static int* test2()
2
{
3
    static int x[] = {1, 1, 2, 3, 5};
4
    return x;
5
}

Deshalb vermute ich, dass die initialisierung von Array nicht das 
Problem ist.


> Wozu soll das & gut sein?

Ich möchte eine Referenz auf den Zeiger.

von Klaus W. (mfgkw)


Lesenswert?

Bei einem Feld gibt es aber doch keinen expliziten Zeiger in Form einer 
Variable. Nur dann könnte man auch eine Referenz darauf bilden.

von Klaus W. (mfgkw)


Lesenswert?

Vielleicht hast du sowas vor:
1
static int*& test()
2
{
3
    static int feld[] = {1, 1, 2, 3, 5};
4
    static int *x = feld;
5
    return x; // jetzt hoffentlich ohne error!
6
}

Wobei mir momentan aber noch die Phantasie fehlt, wozu das gut sein 
soll, aber das kann auch an mir liegen.

von Klaus (Gast)


Lesenswert?

> Vielleicht hast du sowas vor:static int*& test()
> {
>     static int feld[] = {1, 1, 2, 3, 5};
>     static int *x = feld;
>     return x; // error!
> }

Danke, das ist die Lösung! :)

von Udo S. (urschmitt)


Lesenswert?

Klaus schrieb:
>> Vielleicht hast du sowas vor:static int*& test()
>> {
>>     static int feld[] = {1, 1, 2, 3, 5};
>>     static int *x = feld;
>>     return x; // error!
>> }
>
> Danke, das ist die Lösung! :)

Blos für was?
Was bringt dir ein Zeiger auf einen Zeiger der auf das Array zeigt.
Wo ist der Vorteil davon gegenüber einfach feld als int * zurückzugeben?

Mir fehlt wie auch Klaus die Fantasie wozu deine Lösung gut sein könnte.

von Klaus (Gast)


Lesenswert?

Okay, der Code war eine vereinfachte Form des eigentlichen Problems. Bei 
diesem geht es um eine Template-Klasse mit folgenden Konstruktor:
1
template<class T, int S>
2
class Tree
3
{
4
    public:
5
        Tree(Node<T> (& objects)[S]);
6
    // ...

Nun denke ich kann man mit etwas Phantasie das Problem erahnen :)

von Karl H. (kbuchegg)


Lesenswert?

Klaus schrieb:
> Okay, der Code war eine vereinfachte Form des eigentlichen Problems. Bei
> diesem geht es um eine Template-Klasse mit folgenden Konstruktor:
>
>
1
> template<class T, int S>
2
> class Tree
3
> {
4
>     public:
5
>         Tree(Node<T> (& objects)[S]);
6
>     // ...
7
>
>
> Nun denke ich kann man mit etwas Phantasie das Problem erahnen :)

Nicht wirklich.
Das erklärt immer noch nicht, warum die Funktion eine Referenz lieferen 
muss, und nicht einfach nur die Adresse des static Arrays.
Und auch hier in deinem Template frag ich mich, was die Referenz an 
dieser Stelle verloren hat. Der Konstruktor übernimmt sowieso ein Array 
und Arrays werden per Pointer übergeben. Die [S] Angabe ist nichts 
anderes als syntaktischer Zucker, eine andere Schreibweise für einen 
Pointer. Die Referenz bewirkt hier IMHO nichts (*), ausser das sie alles 
syntaxmässig komplizierter macht.


Das hier ....
1
static int* const & test()
2
{
3
    static int x[] = {1, 1, 2, 3, 5};
4
    return x; // error!
5
}
... sollte die Lösung für dein ursprüngliches Problem sein. Aber warum 
da eine Referenz ins Spiel kommen soll, ist auch mir immer noch unklar.


(*) soll bedeuten: Ich sehe nicht, aus welchem Grund hier überhaupt eine 
Referenz sein sollte, bzw. warum man sie hier braucht oder welchen Zweck 
die Referenz hier erfüllen würde. Kann natürlich sein, dass ich einfach 
nur nicht die zündende Idee erkannt habe.

Kann es sein, dass du da einen Trugschluss hast, und der Meinung bist, 
bei ....
1
void foo( int a[] )
2
{
3
  ...
4
}

würde tatsächlich das komplette Array während des Parameter Passings 
umkopiert? Wenn ja, dann muss ich dich enttäuschen. Diese Schreibweise 
(egal ob da jetzt noch eine Arraygröße angegeben ist oder nicht), ist 
nur eine alternative Schreibweise für
1
void foo( int * a )
2
{
3
  ...
4
}

Mehr steckt da nicht dahinter. Arrays werden IMMER per 'Pointer auf das 
erste Argument' übergeben, egal welche Schreibweise du benutzt.

von Rolf M. (rmagnus)


Lesenswert?

Klaus schrieb:
> Ich möchte eine Referenz auf den Zeiger.

Was für einen Zeiger? x ist kein Zeiger, sondern ein Array. Also muß der 
Compiler einen temporären Zeiger anlegen, der auf den Anfang des Arrays 
zeigt. Und mit dem versuchst du, deine Referenz zu initialisieren, was 
nicht erlaubt ist. Deshalb die Fehlermeldung:

Klaus schrieb:
> invalid initialization of non-const reference of type 'int*&' from a
> temporary of type 'int*'


Was auch geht, aber ähnlich sinnfrei wäre, ist, gleich eine Referenz auf 
das Array zurückzugeben:
1
static int (&test())[5]
2
{
3
    static int x[] = {1, 1, 2, 3, 5};
4
    return x;
5
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.