为什么我不能通过void*
引用传递?编译器允许我声明一个具有以下签名的函数:
static inline void FreeAndNull(void*& item)
但是当我尝试调用它时,我收到以下错误:
Error 1 error C2664: 'FreeAndNull' : cannot convert parameter 1 from 'uint8_t *' to 'void *&'
铸造它void*
也不起作用
另外,有什么解决办法吗?
为什么我不能通过void*
引用传递?编译器允许我声明一个具有以下签名的函数:
static inline void FreeAndNull(void*& item)
但是当我尝试调用它时,我收到以下错误:
Error 1 error C2664: 'FreeAndNull' : cannot convert parameter 1 from 'uint8_t *' to 'void *&'
铸造它void*
也不起作用
另外,有什么解决办法吗?
答案是肯定的,您可以通过void*
引用传递 a,而您得到的错误与此无关。问题是,如果你有一个通过引用获取的函数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!
由于指定的调用,上面的代码是非法的,并且有充分的理由。如果我们可以传入myIntArray
into MyFunction
,它将被重新分配以指向一个void*
不是int
数组类型的缓冲区。因此,从函数返回时,您int*
将指向 type 数组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!
作为一个很好的参考,为什么你不能这样做,想想这段代码:
void OtherFunction(int& myInt) {
myInt = 137;
}
double myDouble;
OtherFunction((int)myDouble); // Also error!
这是不合法的,因为如果您尝试将 a 传递给double
一个采用 , 的函数int&
,那么由于int
和double
具有根本不同的二进制表示,您最终会double
用无意义的数据破坏 the 的位。如果这个演员阵容是合法的,就有可能做这样的坏事。
所以简而言之,是的,你可以接受 a void* &
,但如果你这样做,你必须通过真正void*
的 s。正如 Erik 上面所指出的,如果您想释放指针模板并将其归零,那么您可以这样做。
如果你真的想将 auint_8*
传入你的函数,你可以这样做:
uint_8* uPtr = /* ... */
void* ptr = uPtr;
FreeAndNull(ptr);
uPtr = (uint_8*) ptr;
这需要显式转换来告诉编译器“是的,我知道这可能不安全,但无论如何我都会这样做。”
希望这可以帮助!
如果通过引用获取 void *,则必须传递实际的 void *,而不是 uint8_t *。
试试这个:
template<typename T> inline void FreeAndNull(T * & V) { free(V); V = 0; }
编辑:修改示例以更好地反映 OP 的函数名称,并解决 @6502 完全正确的评论。
转换为 void* 不起作用的原因比其他地方解释的要简单得多:除非您明确指定引用,否则转换会创建右值。您不能将右值作为非常量引用传递。
证明给我看?试试这个:
void fun(void * &) {}
int main() { int * x; void * x2 = x; fun(x); }
如果它适合您使用,请尝试以下操作:
void fun(void * const&);
现在不仅铸造工作,它的隐含。
转换为参考可能很危险。它确实会导致您的代码编译,但我不会谈论它的行为:
void fun(void *&){}
int main() { int * x; fun((void*&)x); }
我敢打赌,这会做非常糟糕的事情(tm),因为你实际上是在这里做 reinterpret_cast 而不是静态演员。