Transfer of emptiness * by reference

Why can't I pass void* by reference? The compiler allows me to declare a function with the following signature:

 static inline void FreeAndNull(void*& item) 

But when I try to call it, I get the following error:

 Error 1 error C2664: 'FreeAndNull' : cannot convert parameter 1 from 'uint8_t *' to 'void *&' 

Drop void* does not work.

Also, are there any workarounds?

+4
source share
3 answers

If you take the void * by reference, you must pass the actual void *, not uint8_t *.

Try this instead:

 template<typename T> inline void FreeAndNull(T * & V) { free(V); V = 0; } 

EDIT: A modified sample to better reflect the OP function name, as well as the address @ 6502 is a completely correct comment.

+6
source

Answer: yes, you can pass void* by reference, and the error you get is not related to this. The problem is that if you have a function that takes void* by reference, then you can only pass variables that are actually void* as a parameter. There is a good reason for this. For example, suppose you have this function:

 void MyFunction(void*& ptr) { ptr = malloc(137); // Get a block of raw memory } int* myIntArray; MyFunction(myIntArray); // Error- this isn't legal! 

The above code is illegal due to the specified call and not without reason. If we could pass myIntArray into MyFunction , it would be reassigned to point to a buffer of type void* , which is not an int array. Therefore, when returning from a function, your int* will point to an array of type void* , undermining the type system. This does not mean that C ++ has a strong type system - it is not, but if you are going to undermine it, you must explicitly introduce some casts.

Similarly, you cannot:

 void MyFunction(void*& ptr) { ptr = malloc(137); // Get a block of raw memory } int* myIntArray; MyFunction((void*)myIntArray); // Error- this isn't legal! 

As a good reference, why can't you do this, think about this code:

 void OtherFunction(int& myInt) { myInt = 137; } double myDouble; OtherFunction((int)myDouble); // Also error! 

This is not legal, because if you tried to pass the function that int& took to double , then since int and double have fundamentally different binary representations, you will end up hiding the double bit with meaningless data. If this cast should be legal, one could do Bad Things like that.

So yes, you can take void* & , but if you need it, you have to go through real void* s. As Eric noted above, if you want to free zero too, then pointer patterns will be available.

If you really want to pass this function to uint_8* , you can do it like this:

 uint_8* uPtr = /* ... */ void* ptr = uPtr; FreeAndNull(ptr); uPtr = (uint_8*) ptr; 

This requires explicit casting to tell the compiler, β€œYes, I know this might not be safe, but I'll do it anyway.”

Hope this helps!

+7
source

Casting in void * does not work for a reason that is much simpler than explained elsewhere: casting creates rvalues ​​unless you explicitly specify a link. You cannot pass an rvalue value as a non-constant reference.

Prove it? Try the following:

 void fun(void * &) {} int main() { int * x; void * x2 = x; fun(x); } 

If this suits you, try the following:

 void fun(void * const&); 

Now casting not only works, but also implicitly.

Listing for reference can be dangerous. This really leads to compilation of the code, but I will not talk about its behavior:

 void fun(void *&){} int main() { int * x; fun((void*&)x); } 

My bet is that it will do very, very bad things (tm), since you are actually doing reinterpret_cast here, not a static cast.

+1
source

Source: https://habr.com/ru/post/1339916/


All Articles