Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error: taking address of temporary [-fpermissive] - npc_multivendor

Tags:

c++

No matter what I do, I always get the same error message. Maybe someone has an idea what I could change.

This is my script:

    void SendInventoryCustom(Player* player, Creature* vendor, int guid)
{
    std::vector<ItemList> vendors = GetVendorList();
    ItemList myVendor;
    for(int i = 0; i < vendors.size(); i++)
    {
        if(vendors[i].GetVendor().getGuid() == guid)
        {
            myVendor = ItemList(&vendors[i].GetVendor(), &vendors[i].GetVendor().items);
            break;
        }
    }

    SmsgListInventory inventory_packet(vendor->GetGUID(), player->GetSession(), &myVendor.GetVendor().items, vendors);
    inventory_packet.Send(vendor, player);
}

During compilation I get the following error message:

1266:59: error: taking address of temporary [-fpermissive]

Line 1266 starts with:

myVendor = ItemList(&vendors[i].GetVendor(), &vendors[i].GetVendor().items);

And this ist the Full Script:
http://pastebin.com/DNnyjEeT

I would be very grateful if someone could help me with my problem.
Thanks in advance, Best regards!

like image 975
user3237801 Avatar asked Jan 26 '14 15:01

user3237801


2 Answers

When encountering a warning, you need to understand each term (which might require some research).

In C++, a temporary is an unnamed object that appears when evaluating an expression, for example:

int a = 5 + 3 * 6;

Is equivalent to:

int a = operator+(5, operator*(3, 6));

The result of operator*(3, 6) is a temporary of type int, meaning that the compiler is rewriting the code to something like:

int __1 = 3 * 6;
int a = 5 + __1;

This may happen in many situations, for example:

int foo();

int a = 5 + foo(); // converted to `int __foo = foo(); int a = 5 + __foo;`

So, now getting to the warning, what is the issue with taking the address of a temporary ?

The issue is that the language only guarantees that the temporary lives until the end of the full expression (basically, until ;). Therefore, taking its address (or creating a reference to it), leaves you with a dangling pointer: a pointer which points into the nether.

So, you may formally take the address, but you should never try to access its value afterward...

Pragmatically, the compiler is allowed (and gcc introduced it in 4.7) to reuse the memory occupied by temporary objects from one expression to the other, since they never co-exist. If you use a previously "captured" address to temporary, you might thus accidentally overwrite another object!

Consider:

void foo(int* a, int b) { std::cout << (*a + b) << "\n"; }

int* i = &(5 + 3);
foo(i, 7 + 6);

It can be translated into:

int __1 = 5 + 3;
int* i = &__1;

__1 = 7 + 6;
foo(i, __1); // equivalent to `foo(&__1, __1);`
like image 69
Matthieu M. Avatar answered Nov 08 '22 07:11

Matthieu M.


In the code snipper

&vendors[i].GetVendor()

Applying address-of operator to a non-lvalue object is not permissive as per standard. Some compilers might allow it with warnings or compiler override, but do remember, its ill-formed and should be avoided.

Assign the return value of the function call to an object, a local/non-local lvalue and then take address of the object.

Quoting Standard

§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.

like image 5
Abhijit Avatar answered Nov 08 '22 08:11

Abhijit