通过引用传递空白*

Cas*_*ash 6 c++ pointers reference function void-pointers

为什么我不能通过void*参考传递?编译器允许我使用以下签名声明一个函数:

static inline void FreeAndNull(void*& item)
Run Code Online (Sandbox Code Playgroud)

但是当我尝试调用它时,我收到以下错误:

Error   1   error C2664: 'FreeAndNull' : cannot convert parameter 1 from 'uint8_t *' to 'void *&'
Run Code Online (Sandbox Code Playgroud)

将它投射到void*也不起作用

另外,有任何变通方法吗?

tem*_*def 9

答案是肯定的,您可以通过void*引用传递,并且您获得的错误与此无关.问题是如果你有一个void*通过引用获取的函数,那么你只能传入实际上是void*s作为参数的变量.这是有充分理由的.例如,假设您有此功能:

void MyFunction(void*& ptr) {
    ptr = malloc(137); // Get a block of raw memory
}

int* myIntArray;
MyFunction(myIntArray); // Error- this isn't legal!
Run Code Online (Sandbox Code Playgroud)

由于有明确的原因,上述代码是非法的.如果我们能传递myIntArrayMyFunction,它会得到重新分配指向型的缓冲区void*不是一个int数组.因此,从函数返回时,您int*将指向一个类型的数组void*,颠覆类型系统.这并不是说C++有一个强大的类型系统 - 它没有 - 但如果你要颠覆它,你必须明确地放置一些演员.

你同样不能这样做:

void MyFunction(void*& ptr) {
    ptr = malloc(137); // Get a block of raw memory
}

int* myIntArray;
MyFunction((void*)myIntArray); // Error- this isn't legal!
Run Code Online (Sandbox Code Playgroud)

作为一个很好的参考,为什么你不能这样做,想想这个代码:

void OtherFunction(int& myInt) {
    myInt = 137;
}

double myDouble;
OtherFunction((int)myDouble); // Also error!
Run Code Online (Sandbox Code Playgroud)

这是不合法的,因为如果你试图将double一个函数传递给一个函数int&,那么从那时起,int并且double具有根本不同的二进制表示,你最终会破坏double无意义数据的位.如果这个演员是合法的,就可以做这样的坏事.

所以简而言之,是的,你可以接受一个void* &,但如果你这样做,你必须传入真实void*的.正如Erik上面所指出的那样,如果你想要释放零指针模板是可行的方法.

如果你真的想传入uint_8*你的函数,你可以这样做:

uint_8* uPtr = /* ... */
void* ptr = uPtr;
FreeAndNull(ptr);
uPtr = (uint_8*) ptr;
Run Code Online (Sandbox Code Playgroud)

这需要显式转换来告诉编译器"是的,我知道这可能不安全,但无论如何我都会这样做."

希望这可以帮助!


Eri*_*rik 6

如果您通过引用获取void*,则必须传递实际的void*,而不是uint8_t*.

试试这个:

template<typename T> inline void FreeAndNull(T * & V) { free(V); V = 0; }
Run Code Online (Sandbox Code Playgroud)

编辑:修改样本以更好地反映OP的函数名称,并解决@ 6502的完全正确的评论.

  • @template - 这是对的,但你的回答甚至没有提到左值/右值. (4认同)