web-dev-qa-db-fra.com

Erreur: prise d'adresse temporaire [-fpermissive]

J'examine cela depuis quelques heures, en vain. Fondamentalement, j'ai

struct rectangle {
    int x, y, w, h;
};

rectangle player::RegionCoordinates() // Region Coord
{
    rectangle temp;
    temp.x = colRegion.x + coordinates.x;
    temp.w = colRegion.w;
    temp.y = colRegion.y + coordinates.y;
    temp.h = colRegion.h;

    return temp;
}

// Collision detect function
bool IsCollision (rectangle * r1, rectangle * r2)
{
    if (r1->x < r2->x + r2->w &&
        r1->x + r1->w > r2->x &&
        r1->y < r2->y + r2->h &&
        r1->y + r1->h > r2->y) 
        {
            return true;
        }
    return false;
}

//blah blah main while loop
if (IsCollision(&player1.RegionCoordinates(), &stick1.RegionCoordinates())) //ERROR
{
    player1.score+=10;
    stick1.x = Rand() % 600+1;
    stick1.y = Rand() % 400+1;
    play_sample(pickup,128,128,1000,false);
}

Des idées? Je suis sûr que c'est quelque chose de vraiment évident, mais pour la vie de moi, je ne peux pas le comprendre.

13
Jack Riales

RegionCoordinates() renvoie un objet par valeur. Cela signifie qu'un appel à RegionCoordinates() renvoie une instance temporaire de rectangle. Comme le dit l'erreur, vous essayez de prendre l'adresse de cet objet temporaire, qui n'est pas légal en C++.

Pourquoi IsCollision() prend-il quand même des pointeurs? Il serait plus naturel de prendre ses paramètres par référence const:

bool IsCollision (const rectangle &r1, const rectangle &r2) {
if (r1.x < r2.x + r2.w &&
    r1.x + r1.w > r2.x &&
    r1.y < r2.y + r2.h &&
    r1.y + r1.h > r2.y) {
        return true;
    }
        return false;
}
//blah blah main while loop
if (IsCollision(player1.RegionCoordinates(), stick1.RegionCoordinates())) //no error any more
{
player1.score+=10;
stick1.x = Rand() % 600+1;
stick1.y = Rand() % 400+1;
play_sample(pickup,128,128,1000,false);
}

Puisque IsCollision prend un rectangle * Et vous prenez l'adresse du résultat ici:

if (IsCollision(&player1.RegionCoordinates(), &stick1.RegionCoordinates()))

Vous renvoyez très probablement un rectangle en arrière de RegionCoordinates() qui est une variable temporaire car elle disparaîtra une fois l'instruction if terminée. Si vous affectez le résultat de RegionCoordinates() à une variable, il ne sera plus temporaire et vous pourrez alors en prendre l'adresse:

rectangle r1 = player1.RegionCoordinates() ;
rectangle r2 = stick1.RegionCoordinates() ;
if (IsCollision(&r1, &r2))

Alternativement, vous pouvez prendre les paramètres comme références const, ce qui serait la façon la plus C++ de le faire:

bool IsCollision (const rectangle &r1, const rectangle  &r2)
6
Shafik Yaghmour

Compte tenu du type d'erreur que vous obtenez, je dois supposer que RegionCoordinates() renvoie un objet par valeur, provoquant ainsi la création d'un temporaire , et vous prenez l'adresse de ce temporaire.

L'opérateur address-of requiert une lvalue comme opérande, mais vous l'appliquez à une rvalue (les valeurs temporaires sont rvalues ​​).

Vous pouvez le faire (si vous n'utilisez pas C++ 11, remplacez auto par le type renvoyé par RegionCoordinates):

auto rcPlayer1 = player1.RegionCoordinates();
auto rcStick1 = player1.RegionCoordinates();
if (IsCollision(&rcPlayer1, &rcStick1)) //ERROR
{
    player1.score+=10;
    stick1.x = Rand() % 600+1;
    stick1.y = Rand() % 400+1;
    play_sample(pickup,128,128,1000,false);
}

Alternativement, vous pouvez modifier IsCollision afin qu'il accepte les références plutôt que les pointeurs, comme suggéré par Angew dans sa réponse .

2
Andy Prowl